人工访问模式——如何针对独特的用例进行优化

汉克•哈金斯
软件工程师

根据您的用例,可以通过多种方式通过用户、组、令牌和权限管理Artifactory中的访问。

我想分享一下我们遇到的一些场景,以及我们如何优化以获得更好的性能,以及我们希望在即将到来的平台更改中迁移到哪里。

视频记录

大家好,欢迎来到我预先录制的关于人工访问模式的会议,以及如何针对独特的用例进行优化。我叫汉克·哈金斯。我是第一资本的高级软件工程师。让我们从这里开始。简单介绍一下我。我在Capital One做了五年的开发人员。实际上,这五年中有四年我都在和Artifactory合作。

我们的团队正在积极支持Artifactory作为二进制存储的企业解决方案,我们正在确保平台和AWS的稳定性,并为我们的内部开发人员社区提供支持,因为他们使用Artifactory。今天的议程,我想做的第一件事是对Artifactory安全管理实体做一个简要的概述,这样大家就能理解了。然后回顾我们需要解决的两个不同的问题,以及它们的要求,我们最终是如何实现它们的以及我们遇到了哪些挑战。然后我们将以设计访问模式时的一些提示和学习结束,并看看Artifactory的下一步发展方向,这实际上是非常令人兴奋的事情。让我们从这里开始。所以Artifactory安全管理实体,如果您一直在使用Artifactory,这些对您来说可能非常熟悉。但我只是想过一遍这些,就像我说的,确保每个人都在同一个页面上并且理解我们将要讨论的内容。首先,我们有用户。

用户是访问平台的最低级别标识符。因此,所有请求都绑定到一个用户,包括未经过身份验证的请求,这些请求实际上绑定到默认的匿名用户。用户或管理员用户可以全局访问该平台。

它们取代了所有其他访问。如果你把一个用户标记为管理用户,这就是你所需要的,他们将拥有对整个平台的全局访问权。在用户之后,我们有组,它是多个用户的集合。它只是提供了一种更好地为更大的用户集组织访问的方法。

它们可以在内部定义,也可以从外部源(例如Active Directory)导入组。用户也是一样,你可以有管理组和所有用户在管理组将具有全局访问权限,就像管理用户一样。在组之后,我们可能有一个更有趣的安全管理实体,权限,这是所有奇迹发生的地方。这就是定义所有非管理访问规则的地方。

如果你定义…你要做的第一件事就是定义它所应用的资源,这些资源可以是存储库、构建、发布包、这些包的目的地和管道源。2022世界杯阿根廷预选赛赛程然后,一旦您定义了权限适用于哪些资源,您将定义哪些用户和/或组可以访问2022世界杯阿根廷预选赛赛程这些资源,然后您可以修改他们拥有的访问级别,以便他们可以读取、注释、部署、删除、覆盖和管理访问。最后这里,在底部,我们有访问令牌。

访问令牌可用于授予临时访问,由任何定义要为之创建令牌的组。

出于本节课的目的,我们将主要关注用户、组和权限,而不是令牌。但是令牌非常有趣,如果您希望在组织中授予临时访问权限,则绝对值得一看。因此,对于这里的第一个问题,我们想要创建一个自助的Docker命名空间访问管理情况。这是什么意思呢?

我们需要为用户提供管理访问大型中央Docker存储库中单个Docker命名空间文件夹的能力。

这个的需求是,我们将使用一个外部的无状态应用程序web应用程序进行自助服务,用户可以登录到它,管理对其命名空间的访问,所有这些状态实际上都保存在Artifactory中。它将完全使用rest api与Artifactory交互来查看和编辑这些访问。在这个应用程序中,我们想要做的一件重要的事情是,当用户登录时,他们需要能够看到他们可以访问的所有名称空间的列表。所以我们需要能够填充Docker命名空间文件夹列表。

当他们登录时,获取并显示给他。

这是我们在那个应用中真正需要的东西,这是一个非常重要的要求。然后,我们将对每个命名空间文件夹进行两级访问。因此,我们有名称空间管理员,他们具有读取、注释、部署和删除访问权限。

删除实际上与覆盖具有相同的访问级别。因此,命名空间管理员可以删除Docker镜像,或者只是重新上传和覆盖Docker镜像,因为他们认为合适。然后我们还有命名空间成员,它与admin非常相似,只是没有Delete访问权限。所以他们可以阅读,注释和部署。访问本身应该被授予对命名空间文件夹和任何东西的访问在Docker存储库中。因此,出于本演示的目的,我们有一个名为Docker local的存储库。这里有两个命名空间文件夹,命名空间1和命名空间2。我知道的好名字。这就是我们要看的顶层文件夹是命名空间,所以他们可以访问命名空间下的任何东西如果他们有权访问命名空间。那么我们如何实现这个呢?

这是我们漂亮的小仓库。显然,我们需要一个与该名称空间相关联的权限。我们决定使用的命名约定实际上是一个大写N的前缀,只是为了将我们的命名空间权限与Artifactory中的所有其他权限分开。这就是带前缀的命名空间这就是我们命名权限的方式。然后我们还加入了一个同名的小组。这个组有点特别。

它不允许任何访问权,我马上就会解释为什么我们有它。现在,这只是一个秘密。让我们仔细看看这个许可。

你也许能猜出我们要用的是什么。但如果你看左边,很明显,我们要用include模式指向Docker本地存储库,无论名称空间是什么,namespace1/♬♬双星让我们,他们可以访问名称空间1下的任何东西任意数量的文件夹,如果我们只有一个星号,它就会是直接在名称空间1文件夹下的任何东西所以我们必须在这里有一个双星。然后个人用户,如果他们是管理员用户,我们给他们读取,注释,部署,删除,如果他们是会员,读取,注释,部署。这里我们有两个管理员用户的例子,还有一个成员用户也有一些很有创意的名字。

好了。那么我们为什么会有这个群体呢?为什么会在这里?组本身具有与权限相同的用户。我们创建这些组的原因实际上是为了填充名称空间列表。当时,我们无法获取用户的权限列表但我们可以通过get user details API获取用户的组列表。所以这些组实际上更像是一个标签,说明这个用户可以访问这个命名空间,专门用于填充命名空间列表。专门为这个创建一堆组似乎有点脏,但你知道,我们就是这么做的。这就是我们所做的。那么我们采用这种方法会遇到哪些挑战呢?很明显,挑战一就是我刚才说的,我们缺少有效的权限API,它会给我们一个用户的权限列表所以我们不需要所有这些组。

我们没有那个API。因此,我们必须创建所有这些组,以便有效地列出用户可以访问的所有名称空间。

挑战二,一些名称空间超出了组允许的名称长度。所以组名有64个字符的限制。我们的一些用户有非常非常长的命名空间。因此,我们最终不得不截断一些组名,以使它们的长名称空间能够正常工作。最后,我们只强制使用更短的命名空间因为如果你开始截断组名,你可能会遇到一些情况,你有两个很长的命名空间名称,后缀可能有一点不同,如果你把它们截断为64个字符,它们可能是相同的组名,然后你就有问题了,所以这就是我们必须开始强制使用的地方,因为我们无法维持。挑战三,我们遇到了一些性能问题。

随着存储库的增长,我们最终在这个Docker存储库上拥有了数千个,我想,超过20,000个或更多的权限。这暴露了平台本身的一些问题,我们实际上需要修补以解决这些问题。幸运的是,JFrog很乐意与我们合作,我们也解决了这个问题。

但显然,这个解决方案对我们有用,它只是给我们带来了一些问题。事实上,我们至今仍在使用它。问题二,我们是否需要允许我们的自助服务Docker命名空间是公共的还是私有的。这意味着什么呢?因此,我们需要为用户提供创建可公开访问的Docker命名空间的能力。我所说的公开,是指所有内部开发者Artifactory都不能访问互联网。所以它只是在Capital One内部,所有的开发人员都可以访问公共命名空间。这样他们就可以从这个公共命名空间中提取图像。然后,私有名称空间仅是具有部署访问权限、能够访问拉取图像、甚至能够在Artifactory中看到该名称空间的用户。那么这个项目的条件是什么呢?

就像我刚才说的,公共Docker名称空间需要是匿名的,或者任何经过身份验证的用户都可以读取。然后私有Docker命名空间应该只有命名空间管理员和命名空间成员可以读。最后,你们知道,问题一的所有要求仍然适用。

我们仍然有自助服务管理应用程序在运行。所以所有这些都需要继续发挥作用。所以这个要求更少,但是也要记住第一个的所有内容。那么我们该怎么办呢?我们如何实现这一点?我们已经有了每个命名空间的权限和组。所以我们对自己说,也许我们可以在现有的范围内工作,为什么要增加更多的东西呢?

我们还是坚持现有的吧。这就是我们所做的。对于私有命名空间,权限没有区别,它有相同的Docker本地存储库,有相同的include模式,用户是admin和membertwo用户。你知道,只要没有其他权限授予对这个命名空间的访问它实际上是私有的,所有有访问权限的都是这两个用户。那么什么是公共许可呢?

这几乎是一样的,只是添加了一个具有读访问权限的匿名用户。还有一个组,我们调用所有有读权限的用户。因此,你可以创建一个组,当新用户创建时,它会自动添加用户。因此,您可以拥有一个包含所有用户的组。

我想,对于我们的用例,我们导入了一个活动目录组里面有所有的用户,所以我们最终只使用那个组。但你绝对可以在Artifactory中创建一个包含所有用户的组。不幸的是,我们发布了这个产品,你可以从这个漂亮的图形中看到,它并不是很顺利。

我们有用户报告了大量的Docker轮询延迟,包括经过身份验证的和未经过身份验证的,所以我们必须从我们所做的事情中快速恢复,并回到绘图板上,找出如何做得更好。发生了什么,问题是什么?显然,我们添加的新东西,匿名用户和所有用户组被添加到所有现有权限中,实际上增加了一些延迟。所以我们想知道为什么会发生这种情况?所以我们和JFrog合作。它们实际上产生了一些非常有趣的信息。这就是我们讨论Artifactory安全映射缓存的原因。

这是什么?为了让Artifactory更快地检查传入请求的访问,它实际上缓存了安全对象的映射。在这个小图表中,箭头代表了一个缓存映射。用户映射到存储库,存储库,映射到权限,当这些请求进来时,它会很快检查这些缓存映射但如果你做的事情与缓存映射流的方式不一致,你可能会遇到一些高延迟。这正是发生在我们身上的事。在这里,我们让用户映射存储库,这些存储库映射到权限,我们有组映射存储库映射到权限。这意味着什么呢?让我们看一个例子。一个示例请求,作为工件正在通过这些映射检查访问。它要做的第一件事是检查用户有权访问的存储库。如果你在做,比如说,我在匿名地从Docker本地存储库请求一些东西。首先要检查的是,匿名用户是否有权访问Docker本地存储库?如果是这样,那么它将检查每个适用于具有匿名用户的Docker本地存储库的权限。

一个接一个地,它会遍历所有的元素。所以我想你可以看出我们的问题出在哪里了。这正是发生在我们身上的事。

对于这个Docker本地存储库,我们有数千个匿名用户权限。所以缓存映射本身并没有给我们带来什么好处。因为它必须逐个遍历应用于该用户的存储库的每个权限,也就是所有权限。因此,它必须通过20,000个权限来检查非匿名用户是否可以访问Docker本地存储库中的特定对象。所以它基本上要检查每一个的包含模式。

这是否适用于这个名称空间?只要继续运行,Docker的请求就会大大减慢。假设用户,它没有发现用户有访问存储库的权限,或者即使它有访问存储库的权限,但权限没有授予它请求的特定东西的权限,接下来它要做的是检查用户所在的所有组。它会遍历用户拥有的所有组,检查每个组,看看组是否有权访问存储库,它会检查应用于该存储库和该组的所有权限。显然,最快的方法是让用户直接获得存储库的权限,这是最快的方法,用这个缓存映射查找,如果是组授予,也不会慢太多,只是慢一点。如果用户有很多组,这也会导致问题因为它必须遍历每个组并检查那个组是否有权访问你试图请求的内容。所以你一定要限制你有多少组。您肯定希望限制每个存储库的权限。这是我们从Artifactory安全映射缓存中学到的两个非常重要的东西。我们回头看看这里的情况。

发生了什么事?对,这两个,这两个家伙。通过让匿名用户拥有这些权限,就像我之前解释的那样,它必须遍历所有权限,以查看匿名用户是否有权访问您试图请求的特定名称空间。所有用户组也是一样,即使你通过了身份验证,如果你试图从Docker本地请求Docker映像,它也需要做同样的事情,它需要经过用户本身,假设用户本身没有访问那个命名空间的权限。

你只是想从别人的命名空间,公共命名空间中提取图像,你需要做同样的事情,它需要遍历所有的权限。所以这两个都是问题。所以我们必须想办法用不同的方式来做这件事,从而大大加快这些分辨率。所以我们最终做的是把我们的仓库分成两个。所以Docker本地,我们决定为所有的公共命名空间提供服务。然后我们有一个单独的Docker私有本地存储库,它将拥有我们的私有命名空间。

在这种情况下,命名空间权限本身是非常相似的,唯一的区别是一个额外的权限,我们将调用一个公共读,这是在Docker上,本地的,它授予公共读访问整个存储库。这种方法肯定更有效率。我们会看到更多的细节。就像我说的,公共许可,和我们在第一个问题中看到的完全一样。

它在同一个Docker本地仓库,相同的include模式,用户在那里有相同的访问权限。因此,与私有许可的唯一区别是存储库。所以不是Docker本地,它会应用到Docker私有本地存储库。

同样的include模式,同样的用户访问。好了,我强调了它们的区别,以防你们没注意到。然后我们有公共读权限,它在Docker本地存储库上,不需要包含模式,它适用于所有内容。这就是我们的匿名读取和所有用户读取权限。

这就快多了如果匿名请求来了,对于公共命名空间,它会检查是否能访问Docker本地?是的。然后它会遍历Docker本地的每个权限

匿名用户。你猜怎么着?现在只剩一个了。所以嘣,马上就搞定了。

所有用户组都是一样的,情况也一样。所以从缓存映射的角度来看更快。然后,如果你请求,比如说,你试图匿名请求一个私有的,来自私有命名空间的东西,首先,它会检查,匿名用户是否有权访问这个私有存储库?不。所以马上,403被禁止了。

好了。所以它更快。你可以肯定地说,Artifactory在设计时就考虑到了拆分存储库,在单个存储库上拥有一堆权限,这是它允许的一种方法,但这看起来不像是Artifactory的设计方式,它确实鼓励你拆分存储库。让我们来看看我们遇到的挑战。

显然,我们的原始设计对用户造成了影响,这是我们应该预见到的,我们应该更好地进行测试。

有效的性能测试非常重要。你肯定想要确保你将要对生产做的事情,你已经彻底确保不会造成任何严重的影响。我觉得我们肯定可以做得更好的测试。所以这绝对是我们遇到的最大挑战。另外,我并没有提到,我们的回滚过程很慢。

我们将其发布到生产中,显然,我们现在有成千上万的权限使用这个匿名用户,这个所有用户组在那里。

为了解决这个问题,我们必须反复检查并从这数千个权限中删除这些权限。这花了一些时间。所以,你知道,很明显,我们想给我们的用户提供立即的救济,或者至少尽可能快。在这种情况下,需要一段时间才能完成,更新数千个权限不是一个快速的过程。这是我们面临的另一个问题。实际上,我认为我们还需要写脚本来检查和恢复更改。

我们还没准备好。那也很好。接下来是挑战三,我们必须打破单一回购的思维模式……从建立Artifactory开始,我们实际上每个包类型只有一个repo。

它只是让我们更容易管理,所以我们已经这样做了一段时间,不幸的是,随着我们的Docker存储库规模的增长,它……它变得难以管理,特别是在我们试图强制执行的新许可模型下。

这在未来是不可行的,所以当我们做出决定时,我们将把它分成几个部分,我们将有一个公共的一面和一个私人的一面。老实说,在这一点上,我们无疑是朝着将我们的存储库分解成更小的部分的方向前进。

现在越来越多了。我们希望在团队层面上有更多的合作。每个团队的存储库。尽管它会极大地增加我们拥有的存储库的数量,但它绝对是正确的方向,在访问管理方面,它肯定会加强这一点。所以在设计访问模式时的技巧和学习。

显然,我首先要指出的是我们从JFrog支持中学到的非常有趣的东西,即Artifactory安全映射缓存,记住这一点非常有趣,如果您能够习惯思考Artifactory解析这些访问实体的方式,那么您可以将其应用于任何您想要计划的情况。无论你想解决的用例是什么,我都要记住这一点,这绝对是我之前给出的两个技巧,你不想让一个用户拥有太多的组,你也不想让一个存储库拥有太多的权限。

这两件事也一定要记住。

就是这样产生的。其次,尽可能与JFrog解决方案团队合作,你知道,他们可能无法预见可能出现的每一种情况,但他们肯定可以借鉴过去帮助其他客户的经验,有时是非常大的客户。所以他们有处理大规模解决方案的经验。所以他们有一些,他们肯定有一些知识当谈到如何最好地实施某些事情时。所以我一定会使用JFrog的解决方案,特别是如果你打算对你的平台进行一些大规模的改变。

非常非常重要。然后还要理解所有可能起作用的Artifactory约束,例如,最大组名,长度。

我们在Artifactory中遇到了类似的事情,这些事情肯定会影响到你,而你一开始并没有考虑到它们,但你为这些事情做计划是非常重要的,因为如果你实现了95%的解决方案,然后你意识到5%的客户,我们需要迁移的东西,我们不能,因为我们遇到了这个限制,我们甚至没有考虑到,这是你不想遇到的事情因为它会推迟你的时间线,它会让你的用户头疼,这是需要非常非常小心的事情。所以一定要记住。

此外,性能测试有效,与长期预期的数据规模。虽然你的规模现在可能只有几百个Docker命名空间,但将来,你会有上万个。所以如果你能在这个范围内测试它,看看你不会遇到任何情况。

这非常非常有帮助。所以这也是值得思考的问题。最后,要有一个回滚计划。

在发布新内容时,最好有一个回滚计划。而且,你知道,即使没有一个回滚计划,也有一个B计划,如果你能做一些事情来立即缓解问题,如果他们出现,也许不是一个完整的回滚,但是你知道,一些中间的解决方案,将有助于缓解问题。拥有它也总是好的。以上就是我们从这两个问题中得到的一些建议和经验。那么Artifactory的下一个目标是什么呢?

项目,就是这样。717版本发布了这些新项目,这是一种组织存储库构建、发布包和管道的新方式,更像是一个团队的规模,你知道,一个团队的资源,只是把它们聚集在一起,然后让他们灵活地控制对自己资源的访问。2022世界杯阿根廷预选赛赛程伴随着这些项目,你会得到这些全球性和项目性的角色,它们是实际上与权限非常相似,但它们专门适用于项目。它们也可以应用于资源环境。所以你可以给你的资源贴上标签,我猜,开发环境2022世界杯阿根廷预选赛赛程,生产环境,然后你可以让这些角色专门应用于这些不同的环境,这真的很有趣。

这是我们非常想研究的领域。

我们还没有做太多的项目,但这绝对是我们想要尝试的方向。那么,是什么让项目变得伟大呢?

他们正在从平台管理员那里转移粒度访问管理,并将其更多地转移给团队来管理自己。因此,虽然有更多的访问管理分发出去是件好事,但我们可能要小心我们提供了多少灵活性。

我们有很多需要考虑的安全审计问题,我们还需要确保在那里有一个职责隔离。

你知道,你不想让你的用户有伤害自己的能力。所以在分配这种控制的时候你必须要小心。就像我之前说的,这是另一个例子,通过应用程序团队和环境将这些单一存储库分解成更小的存储库。所以,是的,这绝对是Artifactory试图让我们进入的方向。希望在接下来的几个月里,我们可能会朝着这个方向前进。所以,朝那个方向发展绝对是件好事。在这些项目中,很重要的一点是记住,你需要了解新的基于角色的访问控制是如何被缓存来优化性能的,就像我们之前看到的缓存,那是在项目出现之前,这些项目可能会有一些新的缓存结构。

我有一种感觉,它可能与他们之前的有点相似,但可能只是角色而不是权限。

但这是我们可以与JFrog讨论的问题,并确保我们在执行新项目结构时牢记这一点。就是这样。今天就到这里。

非常感谢大家观看我的疗程。希望你学到了一些东西。

如果你们有任何问题,我肯定会在这里聊天,我希望你们有好好休息一下你的沼泽。再次感谢。

要么释放,要么死亡