密钥斗篷中的资源,范围,权限和策略


81

我想使用Keycloak的授权系统创建一个相当简单的基于角色的访问控制系统。Keycloak正在替换的系统允许我们创建一个“用户”,该用户是一个或多个“组”的成员。在这种传统系统中,通过组成员身份(向组分配了权限)或直接向用户授予权限,授予用户“权限”以访问约250个“功能”中的每一个。

我想将旧系统映射到密钥斗篷授权。

对我来说,将现有系统中的每个“功能”映射到一个密钥库资源和一组密钥库作用域应该很简单。例如,“ viewAccount”功能显然会映射到“ account”资源和“ view”范围;和“ viewTransaction”映射到“事务”资源...但是,最佳实践是仅创建一个“视图”作用域,并在多种资源(帐户,交易等)中使用它吗?还是应该创建“ viewAccount”范围,“ viewTransaction”范围等?

同样,我对权限有些困惑。对于资源和范围的每种实用组合,是否通常创建许可?如果有多个权限匹配给定的资源/范围,Keycloak会做什么?我猜想Keycloak的目的是允许我针对资源和范围配置权限矩阵,例如,我可以拥有访问“帐户”的权限和“查看”范围的权限,因此我将拥有权限查看帐户?

我之所以这样问,是因为所有这些的结果似乎是我原来的“ viewAccount”功能最终创建了一个“ Account”资源,“ View”范围和一个“ viewAccount”权限,这似乎使我回到了原来的状态。如果正确,那很好。

最后,显然,我需要一套确定是否应应用viewAccount的策略。但是我是否对,这意味着我需要一个用户可能属于的每个旧组的策略吗?例如,如果我具有“服务台”角色,则需要一个“服务台成员身份”策略,然后可以将其添加到“ viewAccount”权限中。它是否正确?

谢谢,

标记


25
Keycloak看起来很成熟并且功能强大,但是它确实可以做的仍然是个谜,因为问题太多,答案却很少。我是在问自己您帖子中的所有问题,却找不到任何答案。为什么那里没有好的教程?没人实际使用这种东西吗?还是没有人愿意写它?
Stijn de Witt

3
到目前为止,Keycloak在生产中对我们来说都非常有效,除了授权外,这确实很难解决我的实际问题。但是我同意,有很多关于Keycloak如何执行OIDC的文档,但是还有一个普遍的假设,即我们知道OAuth和OIDC。如果您还不了解OIDC,很难将Keycloak与应用程序问题联系起来,但是对我来说Keycloak是OIDC的简介,这有点难理解22。(Picketlink / Picketbox甚至更糟!)。我发现最好下载并玩它。
Eval医生

6
同意这些评论,密钥斗篷文档和使用案例很糟糕
Olivier

20
Keycloak开发者,请注意这个问题!您的文档非常不错,但是需要更多教程来解决此处提出的问题。您可能还考虑从旧学校的邮件列表迁移到更加用户友好的内容,例如论坛或Stackoverflow。
GGGforce

5
答案较晚,但您的所有假设基本上都是正确的。至于什么是最佳实践,我认为很难说,因为这种能力是非常新的。甚至连kc开发人员都不知道此时的最佳实践。
cen

Answers:


119

我知道我迟到了2年多,但我想我会分享我所知道的东西,并希望减轻以后读者的痛苦。完全透明-我绝不是Keycloak / OAuth / OIDC专家,我所了解的主要是来自阅读文档,书籍,优秀的YouTube和使用该工具。

这篇文章将由两部分组成:

  1. 我将尽我所能回答您所有的问题
  2. 我将向您展示所有如何在Keycloak中处理策略/作用域/权限的方法,而无需部署单独的应用程序,以便更好地理解该线程中的一些核心概念。请注意,尽管这主要是为了使您入门。我正在使用Keycloak 8.0.0

第一部分

开始之前的一些术语:

  • 在Keycloak,您可以创建2种类型的权限:资源型范围为基础
  • 简而言之,为了Resource-Based获得权限,您可以将其直接应用于资源
  • 为了Scoped-Based获得许可,您可以将其应用于您的范围或范围资源。

最佳实践是仅创建一个“视图”范围,并在多种资源(帐户,交易等)中使用它?还是应该创建“ viewAccount”范围,“ viewTransaction”范围等?

范围代表受保护资源的一组权限。对于您而言,您有2个资源:accounttransaction,因此我倾向于第二种方法。

从长远来看,有一个全球性的view与所有的资源相关的范围内(例如accounttransactioncustomersettlement...)作出授权很难既管理和适应安全需求的变化。

以下是一些示例,您可以查看这些示例以获得设计感

不过请注意-我并不是说您不应该跨资源共享范围。事实上,Keycloak对于资源具有相同的用途type。你可以例如既需要viewAccountviewTransaction范围,以给定的帐户下的读取一个事务(毕竟,你可能需要访问帐户查看交易)。您的要求和标准将严重影响您的设计。

对于资源和范围的每种实用组合,是否通常创建许可?

抱歉,我不完全理解这个问题,所以我会比较宽泛。为了授予/拒绝访问resource,您需要:

  • 定义您的政策
  • 定义您的权限
  • 将策略应用于权限
  • 将您的权限与一个scoperesource(或两者)关联

以便政策执行生效。请参阅授权过程

如何设置所有这些完全取决于您。例如,您可以:

  • 定义单个策略,并在适当的权限下绑定每个策略。

  • 更好的是,定义单个策略,然后将所有相关策略归为一个aggregated策略(一个策略策略),然后将该聚合策略与scope-based权限相关联。您可以将该scoped-based权限应用于资源及其所有关联的范围。

  • 或者,您可以通过利用两种不同的类型进一步分解权限。您可以通过resource-based权限类型专门为您的资源创建权限,并通过权限类型单独将其他权限与范围单独关联scope-based

您有选择。

如果有多个权限匹配给定的资源/范围,Keycloak会做什么?

这取决于

  1. 资源服务器的 Decision Strategy
  2. 每个权限的 Decision Strategy
  3. 每项政策的Logic价值。

Logic值与Java的!运算符相似。可以是PositiveNegative。如果LogicPositive,则该策略的最终评估保持不变。如果为Negative,则否定最终结果(例如,如果策略评估为false,Logic则为Negative,则它将为true)。为简单起见,我们假设Logic始终将设置为Positive

Decision Strategy是我们真正要解决的问题。在Decision Strategy可以是UnanimousAffirmative。从文档中

决策策略

此配置更改了策略评估引擎基于所有评估权限的结果来决定是否应授予资源或范围的方式。肯定是指至少一个许可必须评估一个肯定的决定,才能授予对资源及其范围的访问权限。一致意味着所有权限都必须评估为肯定的决定,以便最终决定也为肯定的。例如,如果对同一资源或范围的两个权限发生冲突(其中一个授予权限,另一个拒绝访问),则在所选策略为肯定的情况下,将授予对资源或范围的权限。否则,任何权限的一次拒绝也将拒绝对资源或范围的访问。

让我们使用一个示例来更好地理解上述内容。假设您有一个具有2个权限的资源,并且有人正在尝试访问该资源(请记住,所有策略LogicPositive为)。现在:

  1. Permission One有一个Decision Strategy设置为Affirmative。它还有3个策略,它们各自对它们进行评估:
    • true
    • false
    • false

由于其中一项策略设置为truePermission One因此设置为true(肯定-仅需要设置为1 true)。

  1. Permission Two有一Decision Strategy组以Unanimous2种策略:
    • true
    • false

在这种情况下Permission Twofalse因为一个策略是错误的(一致-它们都必须是true)。

  1. 现在进行最终评估。如果资源服务器的Decision Strategy设置为Affirmative,访问该资源将被授予因为Permission Onetrue。另一方面,如果资源服务器的Decision Strategy设置为Unanimous,则访问将被拒绝。

看到:

我们将继续讨论。我将Decision Strategy 在第二部分中说明如何设置资源服务器。

因此,例如,我可以有权访问“帐户”和“查看”范围的权限,因此我将有权查看帐户?

简短的答案是肯定的。现在,让我们对此进行扩展:)

如果您具有以下情况:

  1. 资源服务器的Decision Strategy设置为UnanimousAffirmative
  2. 访问account/{id}资源的权限为true
  3. 访问view范围的权限为true

您将被授予查看该帐户的权限。

  • true+true等于或true之下。 AffirmativeUnanimous Decision Strategy

现在如果你有这个

  1. 资源服务器Decision Strategy设置为Affirmative
  2. 访问account/{id}资源的权限为true
  3. 访问view范围的权限为false

你会被授予访问权限查看的帐户。

  • true+falsetrueAffirmative的策略。

这里的要点是,对给定资源的访问也取决于您的设置,因此请小心,因为您可能不需要第二种情况。

但是我是否对,这意味着我需要一个用户可能属于的每个旧组的策略吗?

我不确定Keycloak在2年前的表现如何,但是您可以指定一个基于组的策略,然后直接在该策略下添加所有组。您当然不需要为每个组创建一个策略。

例如,如果我具有“服务台”角色,则需要一个“服务台成员身份”策略,然后可以将其添加到“ viewAccount”权限中。它是否正确?

差不多了 您可以通过多种方式进行设置。例如,您可以:

  1. 创建您的资源(例如/account/{id}),并将其与account:view范围相关联。
  2. 创建基于角色的策略helpdesk在该策略下添加角色
  3. 创建一个Scope-Based名为的权限viewAccount,并将其与绑定在一起scoperesource然后policy

我们将在第二部分中进行类似的设置。

第二部分

Keycloak有一个简洁的小工具,可让您测试所有策略。更好的是,您实际上不需要启动另一个应用程序服务器并部署一个单独的应用程序即可运行。

这是我们要设置的方案:

  1. 我们将创建一个名为 stackoverflow-demo
  2. 我们将bank-api在该领域下创建一个客户
  3. 我们将/account/{id}为该客户定义一个资源
  4. account/{id}将有account:view范围
  5. 我们将bob在新领域下创建一个名为
  6. 我们也将创建三个角色:bank_telleraccount_owneruser
    • 我们不会bob与任何角色相关联。现在不需要。
  7. 我们将设置以下两个Role-Based策略:
    • bank_telleraccount_owner有权访问/account/{id}资源
    • account_owner有权使用account:view范围
    • user 无权访问资源或范围
  8. 我们将使用该Evaluate工具来了解如何授予或拒绝访问权限。

请原谅我,这个例子是不现实的,但我对银行业并不熟悉:)

密钥斗篷设置

下载并运行Keycloak

cd tmp
wget https://downloads.jboss.org/keycloak/8.0.0/keycloak-8.0.0.zip 
unzip keycloak-8.0.0.zip
cd keycloak-8.0.0/bin
./standalone.sh 

创建初始管理员用户

  1. http://localhost:8080/auth
  2. 点击Administration Console链接
  3. 创建管理员用户并登录

有关更多信息,请访问入门。就我们的目的而言,以上已足够。

搭建舞台

创建一个新领域

  1. 将鼠标悬停在域上master,然后单击Add Realm按钮。
  2. 输入stackoverflow-demo作为名称。
  3. 点击Create
  4. 现在应该在左上方说stackoverflow-demo而不是master领域。

请参阅创建新领域

创建一个新用户

  1. 点击Users左侧的链接
  2. 点击Add User按钮
  3. 输入username(例如bob
  4. 确保User Enabled已打开
  5. 请点击 Save

请参阅创建新用户

创建新角色

  1. 点击Roles链接
  2. 点击 Add Role
  3. 添加下列角色:bank_telleraccount_owneruser

同样,也没有与角色的用户联系起来。就我们的目的而言,这不是必需的。

查看角色

创建一个客户

  1. 点击Clients链接
  2. 点击 Create
  3. 输入bank-apiClient ID
  4. 对于Root URL进入http://127.0.0.1:8080/bank-api
  5. 点击 Save
  6. 确保Client Protocolopenid-connect
  7. 更改Access Typeconfidential
  8. 更改Authorization EnabledOn
  9. 向下滚动并点击Save。新Authorization选项卡应显示在顶部。
  10. 单击Authorization选项卡,然后Settings
  11. 确保将Decision Strategy设置为Unanimous
    • 这是资源服务器的 Decision Strategy

看到:

创建自定义范围

  1. 点击Authorization标签
  2. 点击Authorization Scopes>Create弹出Add Scope页面
  3. 输入account:view名称,然后按Enter。

创建“查看帐户资源”

  1. 点击上面的Authorization链接
  2. 点击 Resources
  3. 点击 Create
  4. 输入View Account Resource两者的NameDisplay name
  5. 输入account/{id}URI
  6. account:viewScopes文本框中输入
  7. 请点击 Save

请参阅创建资源

建立您的政策

  1. 再次在Authorization标签下,点击Policies
  2. RoleCreate Policy下拉菜单中选择
  3. 在该Name部分中,键入Only Bank Teller and Account Owner Policy
  4. 在下Realm Roles选择bank_telleraccount_owner角色
  5. 确保将Logic其设置为Positive
  6. 请点击 Save
  7. 点击Policies链接
  8. RoleCreate Policy下拉菜单中再次选择。
  9. 这次Only Account Owner Policy用于Name
  10. Realm Roles选择下account_owner
  11. 确保将Logic其设置为Positive
  12. 请点击 Save
  13. 单击Policies顶部的链接,您现在应该看到新创建的策略。

请参阅基于角色的策略

请注意,Keycloak具有更强大的策略。请参阅管理策略

创建基于资源的权限

  1. 再次在Authorization标签下,点击Permissions
  2. 选择 Resource-Based
  3. 键入View Account Resource PermissionName
  4. ResourcesView Account Resource Permission
  5. Apply Policy选择下Only Bank Teller and Account Owner Policy
  6. 确保将Decision Strategy设置为Unanimous
  7. 请点击 Save

请参阅创建基于资源的权限

ew ...

评估基于资源的权限

  1. 再次在Authorization标签下,选择Evaluate
  2. User输入bob
  3. Roles选择下user
    • 这是我们将用户与我们创建的角色相关联的地方。
  4. Resources选择下View Account Resource,然后单击Add
  5. 单击评估。
  6. 展开View Account Resource with scopes [account:view]以查看结果,您应该看到DENY

在此处输入图片说明

  1. 这是有道理的,因为我们只允许两个角色通过来访问该资源Only Bank Teller and Account Owner Policy。让我们测试一下以确保这是真的!
  2. 点击Back评估结果上方的链接
  3. 将bob的角色更改为account_owner,然后单击Evaluate。现在,您应该看到结果为PERMIT。如果您返回并将角色更改为bank_teller

请参阅评估和测试策略

创建基于范围的权限

  1. 返回本Permissions
  2. Scope-BasedCreate Permission下拉菜单中选择此时间。
  3. 在下Name,输入View Account Scope Permission
  4. 在下Scopes,输入account:view
  5. 在下Apply Policy,输入Only Account Owner Policy
  6. 确保将Decision Strategy设置为Unanimous
  7. 请点击 Save

请参阅创建基于范围的权限

第二次试运行

评估我们的新变化

  1. 返回本Authorization
  2. 点击 Evaluate
  3. 用户应该是 bob
  4. 角色应该是 bank_teller
  5. 资源应View Account Resource点击Add
  6. 点击Evaluate,我们应该得到DENY
    • 同样,这并不奇怪,因为bank_teller可以访问,resource但不能访问scope。在这里,一个许可权评估为true,另一个许可权评估为false。鉴于资源服务器的Decision Strategy设置为Unanimous,最后的决定是DENY
  7. 单击选项卡Settings下的Authorization,然后将更Decision Strategy改为Affirmative,然后再次返回到步骤1-6。这次,最终结果应该是PERMIT(一个权限为真,所以最终决定为真)。
  8. 为了完整起见,请将资源服务器的位置Decision Strategy重新设置为Unanimous。再次返回步骤1至6,但这一次将角色设置为account_owner。这次,最终的结果再次PERMIT变得有意义,因为可以account_owner访问resourcescope

整洁:)希望这会有所帮助。


1
@SANDEEPMACHIRAJU不客气:)好问题!没有足够的字符可以通过注释提供深入的答案,但是您可以使用令牌自省端点。这是所有端点的列表。我认为您也可以使用他们的授权客户端,但是我没有使用它的经验
Andy

7
感谢您的出色回答。
Markus

3
@JWo不客气!Tbh,没有特别的原因。我只是尽可能简化示例,以使任何人入门。我从经验中知道,文档并不是最令人兴奋的东西。至于另一个需要访问银行API的客户端,听起来您可能正在寻找User Management Access (UMA)资源所有者可以向请求方授予对受保护资源的访问权限的地方(至少这是我的解释)。
安迪

3
感谢您抽出宝贵的时间将所有这些放在一起,您肯定正在使世界变得更美好……您应该写一些关于这一切的博客文章!非常有用@Andy
何塞·卡洛斯·

1
@安迪哇!感谢您抽出宝贵的时间来消化所有Auth Services文档并与我们共享。您已经为许多人节省了很多时间的学习!我只有一件事看不到。你说了account_owner has access to the account:view scope。您如何稳定该角色与该范围之间的关系?
相互依存的

5

我一直在寻求通过纯HTTP方法强制执行授权,而不使用适配器,因为Lua没有适配器。希望这个答案能帮助人们寻找基于非适配器的方法。

如果您正在寻找适配器,则快速入门指南是最好的入门指南。特别是spring boot authz示例

对于基于纯HTTP的实现:

步骤1:

Keycloak管理员界面中定义策略和权限

第2步

具有哪些HTTP路径属于哪些资源以及每个路径所需的作用域的内部映射。也可以将其保存在配置文件中。调用特定路由时,请调用Keycloak令牌端点以验证访问令牌的声明。

{
  "policy-enforcer": {
    "user-managed-access" : {},
    "enforcement-mode" : "ENFORCING"
    "paths": [
      {
        "path" : "/someUri/*",
        "methods" : [
          {
            "method": "GET",
            "scopes" : ["urn:app.com:scopes:view"]
          },
          {
            "method": "POST",
            "scopes" : ["urn:app.com:scopes:create"]
          }
        ]
      }
    ]
  }
}

如果您使用的是适配器,但未指定路径或资源,则适配器将从内部在Keycloak中搜索路径和资源。

第三步:

使用令牌端点来获取或评估权限。您可以使用response_mode参数获取最终决定(是否提供访问权限)或检索整个权限。

curl -X POST \
  http://${host}:${port}/auth/realms/${realm}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "permission=Resource A#Scope A"

如果授权请求未映射到任何权限,则将403返回HTTP状态代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.