keycloak 中的资源、范围、权限和策略
Resources, scopes, permissions and policies in keycloak
我想使用 Keycloak 的授权系统创建一个相当简单的基于角色的访问控制系统。 Keycloak 正在替换的系统允许我们创建一个 "user",他是一个或多个 "groups" 的成员。在这个遗留系统中,一个用户被授予 "permission" 访问大约 250 个 "capabilities" 中的每一个,要么通过组成员资格(组被分配权限)要么直接授予用户权限。
我想将遗留系统映射到 keycloak 授权。
将现有系统中的每个 "capability" 映射到一个 keycloak 资源和一组 keycloak 范围对我来说应该很简单。例如,"viewAccount" 能力显然会映射到 "account" 资源和 "view" 范围;并且 "viewTransaction" 映射到 "transaction" 资源...但是最好的做法是只创建一个 "view" 范围,并在多个资源(帐户、交易等)中使用它吗?或者我应该创建一个 "viewAccount" 范围、一个 "viewTransaction" 范围等?
同样,我对权限有点困惑。对于资源和范围的每个实际组合,通常的做法是创建权限吗?如果有多个权限与给定的 resource/scope 相匹配,Keycloak 会做什么?我猜 Keycloak 的目的是允许我配置针对资源和范围的权限矩阵,例如,我可以有权访问 "accounts" 和 "view" 范围的权限,因此我将有权查看帐户?
我问是因为所有这一切的结果似乎是我的旧 "viewAccount" 能力最终创建了一个 "Account" 资源,具有 "View" 范围,并且 "viewAccount" 许可,这似乎让我回到了原来的位置。哪个好,如果它是正确的。
最后,显然我需要一组确定是否应应用 viewAccount 的策略。但我是否正确,这是否意味着我需要为用户可能属于的每个遗留组制定策略?例如,如果我有一个 "helpdesk" 角色,那么我需要一个 "helpdesk membership" 策略,然后我可以将其添加到 "viewAccount" 权限。这是正确的吗?
谢谢,
马克
我知道我迟到了 2 年多,但我想我会分享我所知道的,并希望能减轻未来读者的一些痛苦。完全透明 - 我绝不是 Keycloak/OAuth/OIDC 专家,我所知道的主要是阅读文档、书籍、优秀的 YouTube 和使用该工具。
这个post将由两部分组成:
- 我会尽力回答你所有的问题
- 我将向您展示如何在 Keycloak 中使用 policies/scopes/permissions,而无需部署单独的应用程序,以便更好地理解此线程中的一些核心概念。请注意,这主要是为了让你们都开始。我正在使用
Keycloak 8.0.0
.
第一部分
开始之前的一些术语:
- 在Keycloak中,您可以创建2种权限:Resource-Based and Scope-Based.
- 简单地说,对于
Resource-Based
权限,您直接将其应用到您的资源
- 对于
Scoped-Based
权限,您将其应用于您的范围或范围 和 资源。
is it best practice to create just one "view" scope, and use it across multiple resources (account, transaction, etc)? Or should I create a "viewAccount" scope, a "viewTransaction" scope, etc?
范围表示受保护资源的一组权限。在你的例子中,你有 2 个资源:account
和 transaction
,所以我倾向于第二种方法。
在长 运行 中,具有与所有资源关联的全局 view
范围(例如 account
、transaction
、customer
、settlement
...) 使得授权难以管理和适应安全需求的变化。
这里有一些示例,您可以查看这些示例以感受设计
但请注意 - 我并不是说您不应该跨资源共享范围。事实上,Keycloak
允许对具有相同 type
的资源执行此操作。例如,您可能需要 viewAccount
和 viewTransaction
范围来读取给定帐户下的交易(毕竟您可能需要访问该帐户才能查看交易)。您的要求和标准将严重影响您的设计。
For each practical combination of resource and scope, is it usual practice to create a permission?
抱歉,我没有完全理解这个问题,所以我会有点宽泛。为了 grant/deny 访问 resource
,您需要:
- 定义你的 policies
- 定义你的permissions
- 将您的策略应用于您的权限
- 将您的权限关联到
scope
或 resource
(或两者)
政策实施生效。参见 Authorization Process。
如何设置这一切完全取决于您。例如,您可以:
定义单独的策略,并将每个策略绑定到适当的权限下。
更好的是,定义单独的策略,然后将所有相关策略分组在 aggregated
策略(策略的策略)下,然后将该聚合策略与 scope-based
相关联允许。您可以将 scoped-based
权限应用于资源及其所有关联范围。
或者,您可以利用这两种不同的类型进一步分解您的权限。您可以通过 resource-based
权限类型仅为您的资源创建权限,并通过 scope-based
权限类型单独将其他权限仅与范围相关联。
你有选择。
If there are multiple permissions matching a given resource/scope, what does Keycloak do?
这取决于
- 资源服务器的
Decision Strategy
- 每个权限的
Decision Strategy
- 每个策略的
Logic
值。
Logic
值类似于 Java 的 !
运算符。它可以是 Positive
或 Negative
。当 Logic
为 Positive
时,策略的最终评估保持不变。当其 Negative
时,最终结果被否定(例如,如果策略评估为 false 且其 Logic
为 Negative
,则它将为 true
)。为简单起见,我们假设 Logic
始终设置为 Positive
。
Decision Strategy
才是我们真正想要解决的问题。 Decision Strategy
可以是 Unanimous
或 Affirmative
。从文档中,
Decision Strategy
This configurations changes how the policy evaluation engine decides whether or not a resource or scope should be granted based on the outcome from all evaluated permissions. Affirmative means that at least one permission must evaluate to a positive decision in order grant access to a resource and its scopes. Unanimous means that all permissions must evaluate to a positive decision in order for the final decision to be also positive. As an example, if two permissions for a same resource or scope are in conflict (one of them is granting access and the other is denying access), the permission to the resource or scope will be granted if the chosen strategy is Affirmative. Otherwise, a single deny from any permission will also deny access to the resource or scope.
让我们用一个例子来更好地理解上面的内容。假设您有一个具有 2 个权限的资源并且有人试图访问该资源(请记住,Logic
是所有策略的 Positive
)。现在:
Permission One
有一个 Decision Strategy
设置为 Affirmative
。它还有 3 个策略,它们各自评估为:
true
false
false
由于其中一个策略设置为 true
,Permission One
设置为 true
(肯定 - 只有 1 个需要 true
)。
Permission Two
有一个 Decision Strategy
设置为 Unanimous
,有 2 个策略:
true
false
在这种情况下,Permission Two
是 false
,因为一项政策是错误的(一致 - 它们都需要是 true
)。
- 现在是最终评估。如果资源服务器'
Decision Strategy
设置为 Affirmative
,将授予对该资源的访问权限,因为 Permission One
是 true
。另一方面,如果资源服务器的 Decision Strategy
设置为 Unanimous
,访问将被拒绝。
参见:
我们会继续讨论这个问题。我在第二部分解释了如何设置资源服务器的 Decision Strategy
。
so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
简短的回答是肯定的。现在,让我们稍微展开一下:)
如果您遇到以下情况:
- 资源服务器的
Decision Strategy
设置为 Unanimous
或 Affirmative
- 访问
account/{id}
资源的权限是 true
- 访问
view
范围的权限是 true
您将被授予查看帐户的权限。
true
+true
等于Affirmative
或Unanimous
下的true
Decision Strategy
。
现在如果你有这个
- 资源服务器的
Decision Strategy
设置为 Affirmative
- 访问
account/{id}
资源的权限是 true
- 访问
view
范围的权限是 false
您将也被授予查看帐户的权限。
true
+ false
在Affirmative
策略下是true
。
这里的要点是,对给定资源的访问也取决于您的设置,因此请小心,因为您可能不希望出现第二种情况。
But am I right that this means I need a policy for each of the legacy groups that a user could belong to?
我不确定 Keycloak 在 2 年前的表现如何,但您可以指定 Group-Based policy 并根据该策略简单地添加您的所有组。您当然不需要为每个组创建一个策略。
For example, if I have a "helpdesk" role, then I need a "helpdesk membership" policy, which I could then add to the "viewAccount" permission. Is this correct?
差不多。您可以通过多种方式进行设置。例如,您可以:
- 创建您的资源(例如
/account/{id}
)并将其与 account:view
范围相关联。
- 创建一个 Role-Based Policy 并根据该策略添加
helpdesk
角色
- 创建一个名为
viewAccount
的 Scope-Based
权限并将其与 scope
、resource
和 policy
绑定
我们将在第二部分中设置类似的内容。
第二部分
Keycloak 有一个简洁的小工具,可让您测试所有策略。更好的是,您实际上不需要启动另一个应用程序服务器并部署一个单独的应用程序来使其工作。
这是我们要设置的场景:
- 我们将创建一个名为
Whosebug-demo
的新领域
- 我们将在该领域下创建一个
bank-api
客户端
- 我们将为该客户端定义一个名为
/account/{id}
的资源
account/{id}
将具有 account:view
范围
- 我们将在新领域
下创建一个名为 bob
的用户
- 我们还将创建三个角色:
bank_teller
、account_owner
和 user
- 我们不会将
bob
与任何角色相关联。现在不需要这个。
- 我们将设置以下两个
Role-Based
政策:
bank_teller
和 account_owner
可以访问 /account/{id}
资源
account_owner
可以访问 account:view
范围
user
无权访问资源或范围
- 我们将尝试使用
Evaluate
工具来了解如何授予访问权限或
否认。
请原谅,这个例子不切实际,但我对银行业不熟悉:)
Keycloak 设置
下载并运行 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
创建初始管理员用户
- 转到
http://localhost:8080/auth
- 点击
Administration Console
link
- 创建管理员用户并登录
访问Getting Started了解更多信息。就我们的目的而言,以上内容就足够了。
搭建舞台
创建一个新领域
- 将鼠标悬停在
master
领域上,然后单击 Add Realm
按钮。
- 输入
Whosebug-demo
作为名称。
- 点击
Create
。
- 左上角现在应该显示
Whosebug-demo
而不是 master
领域。
创建新用户
- 点击左边的
Users
link
- 点击
Add User
按钮
- 输入
username
(例如bob
)
- 确保
User Enabled
已打开
- 点击
Save
创建新角色
- 点击
Roles
link
- 点击
Add Role
- 添加以下角色:
bank_teller
、account_owner
和 user
同样,不要将您的用户与角色相关联。出于我们的目的,这不是必需的。
创建客户端
- 点击
Clients
link
- 点击
Create
- 为
Client ID
输入 bank-api
- 对于
Root URL
输入 http://127.0.0.1:8080/bank-api
- 点击
Save
- 确保
Client Protocol
是 openid-connect
- 将
Access Type
更改为 confidential
- 将
Authorization Enabled
改为On
- 向下滚动并点击
Save
。一个新的 Authorization
标签应该出现在顶部。
- 单击
Authorization
选项卡,然后单击 Settings
- 确保
Decision Strategy
设置为 Unanimous
- 这是资源服务器的
Decision Strategy
参见:
创建自定义范围
- 单击
Authorization
选项卡
- 点击
Authorization Scopes
> Create
调出 Add Scope
页面
- 在名称中输入
account:view
并按回车键。
创建"View Account Resource"
- 点击
Authorization
上方link
- 点击
Resources
- 点击
Create
- 为
Name
和 Display name
输入 View Account Resource
- 为
URI
输入 account/{id}
- 在
Scopes
文本框中输入account:view
- 点击
Save
制定您的政策
- 再次在
Authorization
选项卡下,单击 Policies
- Select
Role
来自 Create Policy
下拉列表
- 在
Name
部分,输入 Only Bank Teller and Account Owner Policy
- 在
Realm Roles
select 下 bank_teller
和 account_owner
角色
- 确保
Logic
设置为 Positive
- 点击
Save
- 点击
Policies
link
- Select
Role
再次来自 Create Policy
下拉列表。
- 这次使用
Only Account Owner Policy
为Name
- 下
Realm Roles
selectaccount_owner
- 确保
Logic
设置为 Positive
- 点击
Save
- 单击顶部的
Policies
link,您现在应该会看到新创建的策略。
请注意,Keycloak 具有更强大的策略。参见 Managing Policies
创建Resource-Based权限
- 再次在
Authorization
选项卡下,单击 Permissions
- Select
Resource-Based
- 为
Name
输入 View Account Resource Permission
- 在
Resources
下键入 View Account Resource Permission
- 下
Apply Policy
selectOnly Bank Teller and Account Owner Policy
- 确保
Decision Strategy
设置为 Unanimous
- 点击
Save
参见 Create Resource-Based Permissions
呼...
正在评估 Resource-Based 权限
- 再次在
Authorization
选项卡下,select Evaluate
- 在
User
下输入bob
- 下
Roles
selectuser
- 这是我们将用户与我们创建的角色相关联的地方。
- 在
Resources
selectView Account Resource
下点击Add
- 点击评估。
- 展开
View Account Resource with scopes [account:view]
以查看结果,您应该会看到 DENY
。
- 这是有道理的,因为我们只允许两个角色通过
Only Bank Teller and Account Owner Policy
访问该资源。让我们测试一下以确保这是真的!
- 点击评价结果正上方的
Back
link
- 将 bob 的角色更改为
account_owner
并单击 Evaluate
。您现在应该看到结果为 PERMIT
。如果您返回并将角色更改为 bank_teller
,则同样如此
见Evaluating and Testing Policies
创建Scope-Based权限
- 返回
Permissions
部分
- Select
Scope-Based
这次在 Create Permission
下拉菜单下。
- 在
Name
下输入View Account Scope Permission
- 在
Scopes
下输入account:view
- 在
Apply Policy
下输入Only Account Owner Policy
- 确保
Decision Strategy
设置为 Unanimous
- 点击
Save
参见 Creating Scope-Based Permissions
第二次测试运行
评估我们的新变化
- 返回
Authorization
部分
- 点击
Evaluate
- 用户应该是
bob
- 角色应该是
bank_teller
- 资源应该是
View Account Resource
然后点击Add
- 点击
Evaluate
,我们应该得到DENY
。
- 同样,这应该不足为奇,因为
bank_teller
可以访问 resource
但不能访问 scope
。这里一个权限评估为真,另一个为假。鉴于资源服务器的Decision Strategy
设置为Unanimous
,最终决定为DENY
。
- 点击
Authorization
选项卡下的 Settings
,将 Decision Strategy
更改为 Affirmative
并再次返回步骤 1-6。这一次,最终结果应该是PERMIT
(一个权限为真,所以最终决定为真)。
- 为了完整起见,将资源服务器的
Decision Strategy
转回Unanimous
。再次返回步骤 1 到 6,但这一次,将角色设置为 account_owner
。这一次,最终结果又是 PERMIT
,这是有道理的,因为 account_owner
可以访问 resource
和 scope
。
整洁 :) 希望这对您有所帮助。
我希望通过纯 HTTP 方法强制执行授权,而不使用适配器,因为 Lua 没有适配器。希望这个答案可以帮助人们寻找非基于适配器的方法。
如果您正在寻找适配器 quick start guide is the best place to start. Especially the spring boot authz example。
对于纯基于 HTTP 的实现:
第 1 步:
中定义策略和权限
步骤 2
对哪些 HTTP 路径属于哪些资源以及每个路径所需的范围进行内部映射。这也可以保存在configuration file中。调用特定路由时,调用 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"]
}
]
}
]
}
}
如果您使用适配器且未指定路径或资源,适配器将在内部搜索路径和资源from Keycloak。
第 3 步:
使用令牌端点 get or evaluate 权限。您可以使用 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 状态代码。
我知道我来晚了,但让我尽可能多地解释一下。
在 keycloak 中,我们有这样的术语:
资源:用户将访问或执行操作的对象
授权范围:用户可以对特定对象执行的操作
政策:政策
Permission : 映射实际发生在这里
如果您不想遵循手动方式,您可以导出此 JSON 并且所有用户、资源、权限将自动设置 bu keycloak
现在让我们看一个场景:
现在我们几乎没有像这样的资源:
- 账户
- 机器人
- 举报
我们想要实现只有特定用户才能执行特定操作的场景。
设置 Keycloak
创建新领域
- 单击 添加领域 按钮。
- 输入 test-v1 作为名称。
- 点击创建。
创建新角色
- 单击角色
- 单击添加角色
- 创建角色“admin”、“agent”和“super_admin”
创建客户
- 单击客户端 选项卡
- 在客户端 ID 文本框中输入 app-client
- 点击保存
- Select 并再次选择客户端配置其他设置
- 验证客户端协议是 openid-connect
- 将访问类型设置为机密
- 将授权启用设置为开
- 最后点击保存按钮。
- 新的授权 选项卡将出现在顶部。
- Select 在授权选项卡上,然后是设置
检查决策策略是否设置为一致。这是资源服务器策略
创建自定义授权范围
转到授权 选项卡
Select 授权范围 > 然后单击 创建
在文本中输入 scopes:create & scopes:view 并保存值。
创建资源
- 现在转到 资源 选项卡 > 然后单击 创建
- 一一进入,创建如下资源res:account & res:bot & res :报告
- 对于范围文本中的所有资源 select 我们早期创建的两个范围 scopes:create & scopes:view
- 点击保存
创建策略
- 再次在“授权”选项卡中,策略
上的select
- 单击 创建策略 下拉菜单和 select 角色
- 在名称文本框中,Admin
- 领域角色 select 角色 Admin
- 检查逻辑设置为正
- 单击保存,对“代理”和“Super_admin”执行相同操作
- 再次在“授权”选项卡中,策略
上的select
- 单击 创建策略 下拉菜单和 select 聚合
- 在名称文本框中,Admin 或 Super_admin 或 Agent
- 在领域角色 select 角色 Admin & Super_admin & Agent
- 检查逻辑设置为肯定
- 点击保存
创建权限
- 再次在“授权”选项卡中,select 权限
- 单击 创建权限 下拉菜单和 select 基于范围的
- 在名称文本框中,创建帐户
- 在资源箱中,select“资源res:account”
- 在范围 select、scopes:create
- 应用策略管理员
- 我们必须根据要求为所有资源设置相同的权限
创建用户
- 在用户选项卡中创建一个 test 用户
我们不会为其分配任何角色、范围或组以进行测试
让我们评估一下
- 再次在“授权”选项卡中,select 在 评估
- Select我们创建的客户端,app-client
- 在user select创建的用户,test
- 在角色select中创建的用户,admin
- 资源值,res:account
- 单击添加 按钮
- 单击评估按钮
您会看到授权是 permitted 因为 Admin 角色有权执行操作 create 查看资源帐户。
让我们再评估一下
- 再次在“授权”选项卡中,select 在 评估
- Select我们创建的客户端,app-client
- 在user select创建的用户,test
- 在角色select中创建的用户,admin
- 资源值,res:report
- 范围值,范围:创建
- 单击添加 按钮
- 单击评估按钮
您会看到授予是 拒绝 因为只有 Super_Admin 角色有权执行操作 创建 资源 报告.
可以在此处找到具有资源、范围和权限的工作解决方案
keycloak-nodejs-example
只是 运行 已经使用 docker 配置了 Keycloak - 使用 Quick Start guide.
编写
项目中的其他有用示例
- 不使用 Keycloak 登录页面的自定义登录。
- 无状态 Node.js 服务器,不使用会话。 Keycloak 令牌使用 cookie 存储。
- 一个用于检查权限的集中式中间件。没有明确描述的路线无法访问。
- 没有 keycloak.json 的配置。它可用于为多个环境进行配置。例如 — DEV、QA。
- 使用 Keycloak REST API 创建用户、角色和自定义属性的示例。
我想使用 Keycloak 的授权系统创建一个相当简单的基于角色的访问控制系统。 Keycloak 正在替换的系统允许我们创建一个 "user",他是一个或多个 "groups" 的成员。在这个遗留系统中,一个用户被授予 "permission" 访问大约 250 个 "capabilities" 中的每一个,要么通过组成员资格(组被分配权限)要么直接授予用户权限。
我想将遗留系统映射到 keycloak 授权。
将现有系统中的每个 "capability" 映射到一个 keycloak 资源和一组 keycloak 范围对我来说应该很简单。例如,"viewAccount" 能力显然会映射到 "account" 资源和 "view" 范围;并且 "viewTransaction" 映射到 "transaction" 资源...但是最好的做法是只创建一个 "view" 范围,并在多个资源(帐户、交易等)中使用它吗?或者我应该创建一个 "viewAccount" 范围、一个 "viewTransaction" 范围等?
同样,我对权限有点困惑。对于资源和范围的每个实际组合,通常的做法是创建权限吗?如果有多个权限与给定的 resource/scope 相匹配,Keycloak 会做什么?我猜 Keycloak 的目的是允许我配置针对资源和范围的权限矩阵,例如,我可以有权访问 "accounts" 和 "view" 范围的权限,因此我将有权查看帐户?
我问是因为所有这一切的结果似乎是我的旧 "viewAccount" 能力最终创建了一个 "Account" 资源,具有 "View" 范围,并且 "viewAccount" 许可,这似乎让我回到了原来的位置。哪个好,如果它是正确的。
最后,显然我需要一组确定是否应应用 viewAccount 的策略。但我是否正确,这是否意味着我需要为用户可能属于的每个遗留组制定策略?例如,如果我有一个 "helpdesk" 角色,那么我需要一个 "helpdesk membership" 策略,然后我可以将其添加到 "viewAccount" 权限。这是正确的吗?
谢谢,
马克
我知道我迟到了 2 年多,但我想我会分享我所知道的,并希望能减轻未来读者的一些痛苦。完全透明 - 我绝不是 Keycloak/OAuth/OIDC 专家,我所知道的主要是阅读文档、书籍、优秀的 YouTube 和使用该工具。
这个post将由两部分组成:
- 我会尽力回答你所有的问题
- 我将向您展示如何在 Keycloak 中使用 policies/scopes/permissions,而无需部署单独的应用程序,以便更好地理解此线程中的一些核心概念。请注意,这主要是为了让你们都开始。我正在使用
Keycloak 8.0.0
.
第一部分
开始之前的一些术语:
- 在Keycloak中,您可以创建2种权限:Resource-Based and Scope-Based.
- 简单地说,对于
Resource-Based
权限,您直接将其应用到您的资源 - 对于
Scoped-Based
权限,您将其应用于您的范围或范围 和 资源。
is it best practice to create just one "view" scope, and use it across multiple resources (account, transaction, etc)? Or should I create a "viewAccount" scope, a "viewTransaction" scope, etc?
范围表示受保护资源的一组权限。在你的例子中,你有 2 个资源:account
和 transaction
,所以我倾向于第二种方法。
在长 运行 中,具有与所有资源关联的全局 view
范围(例如 account
、transaction
、customer
、settlement
...) 使得授权难以管理和适应安全需求的变化。
这里有一些示例,您可以查看这些示例以感受设计
但请注意 - 我并不是说您不应该跨资源共享范围。事实上,Keycloak
允许对具有相同 type
的资源执行此操作。例如,您可能需要 viewAccount
和 viewTransaction
范围来读取给定帐户下的交易(毕竟您可能需要访问该帐户才能查看交易)。您的要求和标准将严重影响您的设计。
For each practical combination of resource and scope, is it usual practice to create a permission?
抱歉,我没有完全理解这个问题,所以我会有点宽泛。为了 grant/deny 访问 resource
,您需要:
- 定义你的 policies
- 定义你的permissions
- 将您的策略应用于您的权限
- 将您的权限关联到
scope
或resource
(或两者)
政策实施生效。参见 Authorization Process。
如何设置这一切完全取决于您。例如,您可以:
定义单独的策略,并将每个策略绑定到适当的权限下。
更好的是,定义单独的策略,然后将所有相关策略分组在
aggregated
策略(策略的策略)下,然后将该聚合策略与scope-based
相关联允许。您可以将scoped-based
权限应用于资源及其所有关联范围。或者,您可以利用这两种不同的类型进一步分解您的权限。您可以通过
resource-based
权限类型仅为您的资源创建权限,并通过scope-based
权限类型单独将其他权限仅与范围相关联。
你有选择。
If there are multiple permissions matching a given resource/scope, what does Keycloak do?
这取决于
- 资源服务器的
Decision Strategy
- 每个权限的
Decision Strategy
- 每个策略的
Logic
值。
Logic
值类似于 Java 的 !
运算符。它可以是 Positive
或 Negative
。当 Logic
为 Positive
时,策略的最终评估保持不变。当其 Negative
时,最终结果被否定(例如,如果策略评估为 false 且其 Logic
为 Negative
,则它将为 true
)。为简单起见,我们假设 Logic
始终设置为 Positive
。
Decision Strategy
才是我们真正想要解决的问题。 Decision Strategy
可以是 Unanimous
或 Affirmative
。从文档中,
Decision Strategy
This configurations changes how the policy evaluation engine decides whether or not a resource or scope should be granted based on the outcome from all evaluated permissions. Affirmative means that at least one permission must evaluate to a positive decision in order grant access to a resource and its scopes. Unanimous means that all permissions must evaluate to a positive decision in order for the final decision to be also positive. As an example, if two permissions for a same resource or scope are in conflict (one of them is granting access and the other is denying access), the permission to the resource or scope will be granted if the chosen strategy is Affirmative. Otherwise, a single deny from any permission will also deny access to the resource or scope.
让我们用一个例子来更好地理解上面的内容。假设您有一个具有 2 个权限的资源并且有人试图访问该资源(请记住,Logic
是所有策略的 Positive
)。现在:
Permission One
有一个Decision Strategy
设置为Affirmative
。它还有 3 个策略,它们各自评估为:true
false
false
由于其中一个策略设置为 true
,Permission One
设置为 true
(肯定 - 只有 1 个需要 true
)。
Permission Two
有一个Decision Strategy
设置为Unanimous
,有 2 个策略:true
false
在这种情况下,Permission Two
是 false
,因为一项政策是错误的(一致 - 它们都需要是 true
)。
- 现在是最终评估。如果资源服务器'
Decision Strategy
设置为Affirmative
,将授予对该资源的访问权限,因为Permission One
是true
。另一方面,如果资源服务器的Decision Strategy
设置为Unanimous
,访问将被拒绝。
参见:
我们会继续讨论这个问题。我在第二部分解释了如何设置资源服务器的 Decision Strategy
。
so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
简短的回答是肯定的。现在,让我们稍微展开一下:)
如果您遇到以下情况:
- 资源服务器的
Decision Strategy
设置为Unanimous
或Affirmative
- 访问
account/{id}
资源的权限是true
- 访问
view
范围的权限是true
您将被授予查看帐户的权限。
true
+true
等于Affirmative
或Unanimous
下的true
Decision Strategy
。
现在如果你有这个
- 资源服务器的
Decision Strategy
设置为Affirmative
- 访问
account/{id}
资源的权限是true
- 访问
view
范围的权限是false
您将也被授予查看帐户的权限。
true
+false
在Affirmative
策略下是true
。
这里的要点是,对给定资源的访问也取决于您的设置,因此请小心,因为您可能不希望出现第二种情况。
But am I right that this means I need a policy for each of the legacy groups that a user could belong to?
我不确定 Keycloak 在 2 年前的表现如何,但您可以指定 Group-Based policy 并根据该策略简单地添加您的所有组。您当然不需要为每个组创建一个策略。
For example, if I have a "helpdesk" role, then I need a "helpdesk membership" policy, which I could then add to the "viewAccount" permission. Is this correct?
差不多。您可以通过多种方式进行设置。例如,您可以:
- 创建您的资源(例如
/account/{id}
)并将其与account:view
范围相关联。 - 创建一个 Role-Based Policy 并根据该策略添加
helpdesk
角色 - 创建一个名为
viewAccount
的Scope-Based
权限并将其与scope
、resource
和policy
绑定
我们将在第二部分中设置类似的内容。
第二部分
Keycloak 有一个简洁的小工具,可让您测试所有策略。更好的是,您实际上不需要启动另一个应用程序服务器并部署一个单独的应用程序来使其工作。
这是我们要设置的场景:
- 我们将创建一个名为
Whosebug-demo
的新领域
- 我们将在该领域下创建一个
bank-api
客户端 - 我们将为该客户端定义一个名为
/account/{id}
的资源 account/{id}
将具有account:view
范围- 我们将在新领域 下创建一个名为
- 我们还将创建三个角色:
bank_teller
、account_owner
和user
- 我们不会将
bob
与任何角色相关联。现在不需要这个。
- 我们不会将
- 我们将设置以下两个
Role-Based
政策:bank_teller
和account_owner
可以访问/account/{id}
资源account_owner
可以访问account:view
范围user
无权访问资源或范围
- 我们将尝试使用
Evaluate
工具来了解如何授予访问权限或 否认。
bob
的用户
请原谅,这个例子不切实际,但我对银行业不熟悉:)
Keycloak 设置
下载并运行 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
创建初始管理员用户
- 转到
http://localhost:8080/auth
- 点击
Administration Console
link - 创建管理员用户并登录
访问Getting Started了解更多信息。就我们的目的而言,以上内容就足够了。
搭建舞台
创建一个新领域
- 将鼠标悬停在
master
领域上,然后单击Add Realm
按钮。 - 输入
Whosebug-demo
作为名称。 - 点击
Create
。 - 左上角现在应该显示
Whosebug-demo
而不是master
领域。
创建新用户
- 点击左边的
Users
link - 点击
Add User
按钮 - 输入
username
(例如bob
) - 确保
User Enabled
已打开 - 点击
Save
创建新角色
- 点击
Roles
link - 点击
Add Role
- 添加以下角色:
bank_teller
、account_owner
和user
同样,不要将您的用户与角色相关联。出于我们的目的,这不是必需的。
创建客户端
- 点击
Clients
link - 点击
Create
- 为
Client ID
输入bank-api
- 对于
Root URL
输入http://127.0.0.1:8080/bank-api
- 点击
Save
- 确保
Client Protocol
是openid-connect
- 将
Access Type
更改为confidential
- 将
Authorization Enabled
改为On
- 向下滚动并点击
Save
。一个新的Authorization
标签应该出现在顶部。 - 单击
Authorization
选项卡,然后单击Settings
- 确保
Decision Strategy
设置为Unanimous
- 这是资源服务器的
Decision Strategy
- 这是资源服务器的
参见:
创建自定义范围
- 单击
Authorization
选项卡 - 点击
Authorization Scopes
>Create
调出Add Scope
页面 - 在名称中输入
account:view
并按回车键。
创建"View Account Resource"
- 点击
Authorization
上方link - 点击
Resources
- 点击
Create
- 为
Name
和Display name
输入View Account Resource
- 为
URI
输入account/{id}
- 在
Scopes
文本框中输入account:view
- 点击
Save
制定您的政策
- 再次在
Authorization
选项卡下,单击Policies
- Select
Role
来自Create Policy
下拉列表 - 在
Name
部分,输入Only Bank Teller and Account Owner Policy
- 在
Realm Roles
select 下bank_teller
和account_owner
角色 - 确保
Logic
设置为Positive
- 点击
Save
- 点击
Policies
link - Select
Role
再次来自Create Policy
下拉列表。 - 这次使用
Only Account Owner Policy
为Name
- 下
Realm Roles
selectaccount_owner
- 确保
Logic
设置为Positive
- 点击
Save
- 单击顶部的
Policies
link,您现在应该会看到新创建的策略。
请注意,Keycloak 具有更强大的策略。参见 Managing Policies
创建Resource-Based权限
- 再次在
Authorization
选项卡下,单击Permissions
- Select
Resource-Based
- 为
Name
输入View Account Resource Permission
- 在
Resources
下键入View Account Resource Permission
- 下
Apply Policy
selectOnly Bank Teller and Account Owner Policy
- 确保
Decision Strategy
设置为Unanimous
- 点击
Save
参见 Create Resource-Based Permissions
呼...
正在评估 Resource-Based 权限
- 再次在
Authorization
选项卡下,selectEvaluate
- 在
User
下输入bob
- 下
Roles
selectuser
- 这是我们将用户与我们创建的角色相关联的地方。
- 在
Resources
selectView Account Resource
下点击Add
- 点击评估。
- 展开
View Account Resource with scopes [account:view]
以查看结果,您应该会看到DENY
。
- 这是有道理的,因为我们只允许两个角色通过
Only Bank Teller and Account Owner Policy
访问该资源。让我们测试一下以确保这是真的! - 点击评价结果正上方的
Back
link - 将 bob 的角色更改为
account_owner
并单击Evaluate
。您现在应该看到结果为PERMIT
。如果您返回并将角色更改为bank_teller
,则同样如此
见Evaluating and Testing Policies
创建Scope-Based权限
- 返回
Permissions
部分 - Select
Scope-Based
这次在Create Permission
下拉菜单下。 - 在
Name
下输入View Account Scope Permission
- 在
Scopes
下输入account:view
- 在
Apply Policy
下输入Only Account Owner Policy
- 确保
Decision Strategy
设置为Unanimous
- 点击
Save
参见 Creating Scope-Based Permissions
第二次测试运行
评估我们的新变化
- 返回
Authorization
部分 - 点击
Evaluate
- 用户应该是
bob
- 角色应该是
bank_teller
- 资源应该是
View Account Resource
然后点击Add
- 点击
Evaluate
,我们应该得到DENY
。- 同样,这应该不足为奇,因为
bank_teller
可以访问resource
但不能访问scope
。这里一个权限评估为真,另一个为假。鉴于资源服务器的Decision Strategy
设置为Unanimous
,最终决定为DENY
。
- 同样,这应该不足为奇,因为
- 点击
Authorization
选项卡下的Settings
,将Decision Strategy
更改为Affirmative
并再次返回步骤 1-6。这一次,最终结果应该是PERMIT
(一个权限为真,所以最终决定为真)。 - 为了完整起见,将资源服务器的
Decision Strategy
转回Unanimous
。再次返回步骤 1 到 6,但这一次,将角色设置为account_owner
。这一次,最终结果又是PERMIT
,这是有道理的,因为account_owner
可以访问resource
和scope
。
整洁 :) 希望这对您有所帮助。
我希望通过纯 HTTP 方法强制执行授权,而不使用适配器,因为 Lua 没有适配器。希望这个答案可以帮助人们寻找非基于适配器的方法。
如果您正在寻找适配器 quick start guide is the best place to start. Especially the spring boot authz example。
对于纯基于 HTTP 的实现:
第 1 步:
中定义策略和权限步骤 2
对哪些 HTTP 路径属于哪些资源以及每个路径所需的范围进行内部映射。这也可以保存在configuration file中。调用特定路由时,调用 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"]
}
]
}
]
}
}
如果您使用适配器且未指定路径或资源,适配器将在内部搜索路径和资源from Keycloak。
第 3 步:
使用令牌端点 get or evaluate 权限。您可以使用 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 状态代码。
我知道我来晚了,但让我尽可能多地解释一下。
在 keycloak 中,我们有这样的术语:
资源:用户将访问或执行操作的对象
授权范围:用户可以对特定对象执行的操作
政策:政策
Permission : 映射实际发生在这里
如果您不想遵循手动方式,您可以导出此 JSON 并且所有用户、资源、权限将自动设置 bu keycloak
现在让我们看一个场景:
现在我们几乎没有像这样的资源:
- 账户
- 机器人
- 举报
我们想要实现只有特定用户才能执行特定操作的场景。
设置 Keycloak
创建新领域
- 单击 添加领域 按钮。
- 输入 test-v1 作为名称。
- 点击创建。
创建新角色
- 单击角色
- 单击添加角色
- 创建角色“admin”、“agent”和“super_admin”
创建客户
- 单击客户端 选项卡
- 在客户端 ID 文本框中输入 app-client
- 点击保存
- Select 并再次选择客户端配置其他设置
- 验证客户端协议是 openid-connect
- 将访问类型设置为机密
- 将授权启用设置为开
- 最后点击保存按钮。
- 新的授权 选项卡将出现在顶部。
- Select 在授权选项卡上,然后是设置
检查决策策略是否设置为一致。这是资源服务器策略
创建自定义授权范围
转到授权 选项卡 Select 授权范围 > 然后单击 创建 在文本中输入 scopes:create & scopes:view 并保存值。
创建资源
- 现在转到 资源 选项卡 > 然后单击 创建
- 一一进入,创建如下资源res:account & res:bot & res :报告
- 对于范围文本中的所有资源 select 我们早期创建的两个范围 scopes:create & scopes:view
- 点击保存
创建策略
- 再次在“授权”选项卡中,策略 上的select
- 单击 创建策略 下拉菜单和 select 角色
- 在名称文本框中,Admin
- 领域角色 select 角色 Admin
- 检查逻辑设置为正
- 单击保存,对“代理”和“Super_admin”执行相同操作
- 再次在“授权”选项卡中,策略 上的select
- 单击 创建策略 下拉菜单和 select 聚合
- 在名称文本框中,Admin 或 Super_admin 或 Agent
- 在领域角色 select 角色 Admin & Super_admin & Agent
- 检查逻辑设置为肯定
- 点击保存
创建权限
- 再次在“授权”选项卡中,select 权限
- 单击 创建权限 下拉菜单和 select 基于范围的
- 在名称文本框中,创建帐户
- 在资源箱中,select“资源res:account”
- 在范围 select、scopes:create
- 应用策略管理员
- 我们必须根据要求为所有资源设置相同的权限
创建用户
- 在用户选项卡中创建一个 test 用户 我们不会为其分配任何角色、范围或组以进行测试
让我们评估一下
- 再次在“授权”选项卡中,select 在 评估
- Select我们创建的客户端,app-client
- 在user select创建的用户,test
- 在角色select中创建的用户,admin
- 资源值,res:account
- 单击添加 按钮
- 单击评估按钮
您会看到授权是 permitted 因为 Admin 角色有权执行操作 create 查看资源帐户。
让我们再评估一下
- 再次在“授权”选项卡中,select 在 评估
- Select我们创建的客户端,app-client
- 在user select创建的用户,test
- 在角色select中创建的用户,admin
- 资源值,res:report
- 范围值,范围:创建
- 单击添加 按钮
- 单击评估按钮
您会看到授予是 拒绝 因为只有 Super_Admin 角色有权执行操作 创建 资源 报告.
可以在此处找到具有资源、范围和权限的工作解决方案 keycloak-nodejs-example
只是 运行 已经使用 docker 配置了 Keycloak - 使用 Quick Start guide.
编写项目中的其他有用示例
- 不使用 Keycloak 登录页面的自定义登录。
- 无状态 Node.js 服务器,不使用会话。 Keycloak 令牌使用 cookie 存储。
- 一个用于检查权限的集中式中间件。没有明确描述的路线无法访问。
- 没有 keycloak.json 的配置。它可用于为多个环境进行配置。例如 — DEV、QA。
- 使用 Keycloak REST API 创建用户、角色和自定义属性的示例。