keycloak 中的资源、范围、权限和策略 [英] Resources, scopes, permissions and policies in keycloak
问题描述
我想使用 Keycloak 的授权系统创建一个相当简单的基于角色的访问控制系统.Keycloak 正在替换的系统允许我们创建一个用户",他是一个或多个组"的成员.在这个遗留系统中,用户被授予权限"来访问大约 250 项能力"中的每一项,无论是通过组成员身份(组被分配权限)还是直接授予用户权限.
我想将旧系统映射到 keycloak 授权.
将现有系统中的每个功能"映射到一个 keycloak 资源和一组 keycloak 范围对我来说应该很简单.例如,viewAccount"功能显然会映射到帐户"资源和视图"范围;并且viewTransaction"映射到交易"资源......但是最好的做法是创建一个视图"范围,并在多个资源(账户、交易等)中使用它吗?或者我应该创建viewAccount"范围、viewTransaction"范围等吗?
同样,我对权限有点困惑.对于资源和范围的每个实际组合,创建权限是否是通常的做法?如果有多个权限匹配给定的资源/范围,Keycloak 会做什么?我猜测 Keycloak 的目的是允许我针对资源和范围配置权限矩阵,例如,我可以有权访问帐户"和查看"范围的权限,因此我将获得权限查看帐户?
我问是因为这一切的结果似乎是我旧的viewAccount"功能最终创建了一个Account"资源,具有View"范围和viewAccount"权限,这似乎让我回到了哪里我曾是.没问题,如果正确的话.
最后,显然我需要一组确定是否应应用 viewAccount 的策略.但是,这是否意味着我需要为用户可能属于的每个遗留组制定策略?例如,如果我有一个帮助台"角色,那么我需要一个帮助台成员"策略,然后我可以将其添加到viewAccount"权限中.这是正确的吗?
谢谢,
标记
我知道我迟到了 2 年以上,但我想我会分享我所知道的,并希望为未来的读者减轻一些痛苦.完全透明——我绝不是 Keycloak/OAuth/OIDC 专家,我所知道的主要是通过阅读文档、书籍、优秀的 YouTube 和使用该工具.
这篇文章将由两部分组成:
- 我会尽力回答你所有的问题
- 我将向您展示如何在 Keycloak 中使用策略/范围/权限,而无需部署单独的应用程序,以便更好地理解该线程中的一些核心概念.请注意,这主要是为了让您入门.我正在使用
Keycloak 8.0.0
.
第一部分
开始之前的一些术语:
- 在 Keycloak 中,您可以创建两种类型的权限:
- 这是有道理的,因为我们只允许两个角色通过
Only Bank Teller and Account Owner Policy
访问该资源.让我们测试一下,以确保这是真的! - 点击评价结果正上方的
返回
链接 - 将 bob 的角色更改为
account_owner
,然后点击Evaluate
.您现在应该看到结果为PERMIT
.如果您返回并将角色更改为bank_teller
请参阅评估和测试政策
创建基于范围的权限
- 返回
权限
部分 - 这次在
Create Permission
下拉菜单下选择Scope-Based
. - 在
Name
下,输入View Account Scope Permission
- 在
Scopes
下,输入account:view
- 在
Apply Policy
下,输入Only Account Owner Policy
- 确保
Decision Strategy
设置为Unanimous
- 点击
保存
请参阅创建基于范围的权限
第二次试运行
评估我们的新变化
- 回到
Authorization
部分 - 点击
评估
- 用户应该是
bob
- 角色应该是
bank_teller
- Resources 应该是
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
.
Neat :) 希望这会有所帮助.
I want to create a fairly simple role-based access control system using Keycloak's authorizaion system. The system Keycloak is replacing allows us to create a "user", who is a member of one or more "groups". In this legacy system, a user is given "permission" to access each of about 250 "capabilities" either through group membership (where groups are assigned permissions) or a direct grant of a permission to the user.
I would like to map the legacy system to keycloak authorizations.
It should be simple for me to map each "capability" in the existing system to a keycloak resource and a set of keycloak scopes. For example, a "viewAccount" capability would obviously map to an "account" resource and a "view" scope; and "viewTransaction" maps to a "transaction" resource... but 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?
Similarly, I'm a little confused about permissions. For each practical combination of resource and scope, is it usual practice to create a permission? If there are multiple permissions matching a given resource/scope, what does Keycloak do? I'm guessing that the intention of Keycloak is to allow me to configure a matrix of permissions against resources and scopes, so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
I ask because the result of all this seems to be that my old "viewAccount" capability ends up creating an "Account" resource, with "View" scope, and a "viewAccount" permission, which seems to get me back where I was. Which is fine, if it's correct.
Finally, obviously I need a set of policies that determine if viewAccount should be applied. But am I right that this means I need a policy for each of the legacy groups that a user could belong to? 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?
Thanks,
Mark
解决方案I know I'm 2+ years late but I figure I'd share what I know and hopefully alleviate some pain for future readers. Full transparency- I am by no means a Keycloak/OAuth/OIDC expert and what I know is mostly from reading the docs, books, good ol' YouTube and playing around with the tool.
This post will be comprised of two parts:
- I'll attempt to answer all your questions to the best of my ability
- I'll show you all how you can play around with policies/scopes/permissions in Keycloak without needing to deploy a separate app in order to better understand some of the core concepts in this thread. Do note though that this is mostly meant to get you all started. I'm using
Keycloak 8.0.0
.
Part I
Some terminology before we get started:
- In Keycloak, you can create 2 types of permissions: Resource-Based and Scope-Based.
- Simply put, for
Resource-Based
permissions, you apply it directly to your resource - For
Scoped-Based
permission, you apply it to your scope(s) or scope(s) and resource.
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?
Scopes represent a set of rights at a protected resource. In your case, you have 2 resources:
account
andtransaction
, so I would lean towards the second approach.In the long run, having a global
view
scope associated with all your resources (e.g.account
,transaction
,customer
,settlement
...) makes authorization difficult to both manage and adapt to security requirement changes.Here are a few examples that you can check out to get a feel for design
Do note though - I am not claiming that you shouldn't share scopes across resources. Matter of fact,
Keycloak
allows this for resources with the sametype
. You could for instance need bothviewAccount
andviewTransaction
scope to read a transaction under a given account (after all you might need access to the account to view transactions). Your requirements and standards will heavily influence your design.For each practical combination of resource and scope, is it usual practice to create a permission?
Apologies, I don't fully understand the question so I'll be a bit broad. In order to grant/deny access to a
resource
, you need to:- Define your policies
- Define your permissions
- Apply your policies to your permissions
- Associate your permissions to a
scope
orresource
(or both)
for policy enforcement to take effect. See Authorization Process.
How you go about setting all this up is entirely up to you. You could for instance:
Define individual policies, and tie each policy under the appropriate permission.
Better yet, define individual policies, then group all your related policies under an
aggregated
policy (a policy of policies) and then associate that aggregated policy with thescope-based
permission. You could have thatscoped-based
permission apply to both the resource and all its associated scope.Or, you could further break apart your permissions by leveraging the two separate types. You could create permissions solely for your resources via the
resource-based
permission type, and separately associate other permissions solely with a scope via thescope-based
permission type.
You have options.
If there are multiple permissions matching a given resource/scope, what does Keycloak do?
This depends on
- The resource server's
Decision Strategy
- Each permission's
Decision Strategy
- Each policy's
Logic
value.
The
Logic
value is similar with Java's!
operator. It can either bePositive
orNegative
. When theLogic
isPositive
, the policy's final evaluation remains unchanged. When itsNegative
, the final result is negated (e.g. if a policy evaluates to false and itsLogic
isNegative
, then it will betrue
). To keep things simple, let's assume that theLogic
is always set toPositive
.The
Decision Strategy
is what we really want to tackle. TheDecision Strategy
can either beUnanimous
orAffirmative
. From the docs,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.
Let's use an example to better understand the above. Suppose you have a resource with 2 permissions and someone is trying to access that resource (remember, the
Logic
isPositive
for all policies). Now:Permission One
has aDecision Strategy
set toAffirmative
. It also has 3 policies where they each evaluate to:true
false
false
Since one of the policies is set to
true
,Permission One
is set totrue
(Affirmative - only 1 needs to betrue
).Permission Two
has aDecision Strategy
set toUnanimous
with 2 policies:true
false
In this case
Permission Two
isfalse
since one policy is false (Unanimous - they all need to betrue
).- Now comes the final evaluation. If the resource server's
Decision Strategy
is set toAffirmative
, access to that resource would be granted becausePermission One
istrue
. If on the other hand, the resource server'sDecision Strategy
is set toUnanimous
, access would be denied.
See:
We'll keep revisiting this. I explain how to set the resource sever's
Decision Strategy
in Part II.so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
The short answer is yes. Now, let's expand on this a bit :)
If you have the following scenario:
- Resource server's
Decision Strategy
set toUnanimous
orAffirmative
- Permission to access the
account/{id}
resource istrue
- Permission to access the
view
scope istrue
You will be granted access to view the account.
true
+true
is equal totrue
under theAffirmative
orUnanimous
Decision Strategy
.
Now if you have this
- Resource server's
Decision Strategy
set toAffirmative
- Permission to access the
account/{id}
resource istrue
- Permission to access the
view
scope isfalse
You will also be granted access to view the account.
true
+false
istrue
under theAffirmative
strategy.
The point here is that access to a given resource also depends on your setup so be careful as you may not want the second scenario.
But am I right that this means I need a policy for each of the legacy groups that a user could belong to?
I'm not sure how Keycloak behaved 2 years ago, but you can specify a Group-Based policy and simply add all your groups under that policy. You certainly do not need to create one policy per group.
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?
Pretty much. There are many ways you can set this up. For instance, you can:
- Create your resource (e.g.
/account/{id}
) and associate it with theaccount:view
scope. - create a Role-Based Policy and add the
helpdesk
role under that policy - Create a
Scope-Based
permission calledviewAccount
and tie it withscope
,resource
andpolicy
We'll set up something similar in Part II.
Part II
Keycloak has a neat little tool which allows you test all your policies. Better yet, you actually do not need to spin up another application server and deploy a separate app for this to work.
Here's the scenario that we'll set up:
- We'll create a new realm called
stackoverflow-demo
- We'll create a
bank-api
client under that realm - We will define a resource called
/account/{id}
for that client - The
account/{id}
will have theaccount:view
scope - We'll create a user called
bob
under the new realm - We'll also create three roles:
bank_teller
,account_owner
anduser
- We will not associate
bob
with any roles. This is not needed right now.
- We will not associate
- We'll set up the following two
Role-Based
policies:bank_teller
andaccount_owner
have access to the/account/{id}
resourceaccount_owner
has access to theaccount:view
scopeuser
does not have access to the resource or scope
- We'll play around with the
Evaluate
tool to see how access can be granted or denied.
Do forgive me, this example is unrealistic but I'm not familiar with the banking sector :)
Keycloak setup
Download and run 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
Create initial admin user
- Go to
http://localhost:8080/auth
- Click on the
Administration Console
link - Create the admin user and login
Visit Getting Started for more information. For our purposes, the above is enough.
Setting up the stage
Create a new realm
- Hover your mouse around the
master
realm and click on theAdd Realm
button. - Enter
stackoverflow-demo
as the name. - Click on
Create
. - The top left should now say
stackoverflow-demo
instead of themaster
realm.
Create a new user
- Click on the
Users
link on the left - Click on the
Add User
button - Enter the
username
(e.g.bob
) - Ensure that
User Enabled
is turned on - Click
Save
Create new roles
- Click on the
Roles
link - Click on
Add Role
- Add the following roles:
bank_teller
,account_owner
anduser
Again, do not associate your user with the roles. For our purposes, this is not needed.
See Roles
Create a client
- Click on the
Clients
link - Click on
Create
- Enter
bank-api
for theClient ID
- For the
Root URL
enterhttp://127.0.0.1:8080/bank-api
- Click on
Save
- Ensure that
Client Protocol
isopenid-connect
- Change the
Access Type
toconfidential
- Change
Authorization Enabled
toOn
- Scroll down and hit
Save
. A newAuthorization
tab should appear at the top. - Click on the
Authorization
tab and thenSettings
- Ensure that the
Decision Strategy
is set toUnanimous
- This is the resource server's
Decision Strategy
- This is the resource server's
See:
Create Custom Scopes
- Click on the
Authorization
tab - Click on
Authorization Scopes
>Create
to bring upAdd Scope
page - Enter
account:view
in the name and hit enter.
Create "View Account Resource"
- Click on
Authorization
link above - Click on
Resources
- Click on
Create
- Enter
View Account Resource
for both theName
andDisplay name
- Enter
account/{id}
for theURI
- Enter
account:view
in theScopes
textbox - Click
Save
Create your policies
- Again under the
Authorization
tab, click onPolicies
- Select
Role
from the theCreate Policy
dropdown - In the
Name
section, typeOnly Bank Teller and Account Owner Policy
- Under
Realm Roles
select both thebank_teller
andaccount_owner
role - Ensure that
Logic
is set toPositive
- Click
Save
- Click on the
Policies
link - Select
Role
again from theCreate Policy
dropdown. - This time use
Only Account Owner Policy
for theName
- Under
Realm Roles
selectaccount_owner
- Ensure that
Logic
is set toPositive
- Click
Save
- Click on the
Policies
link at the top, you should now see your newly created policies.
Do note that Keycloak has much more powerful policies. See Managing Policies
Create Resource-Based Permission
- Again under the
Authorization
tab, click onPermissions
- Select
Resource-Based
- Type
View Account Resource Permission
for theName
- Under
Resources
typeView Account Resource Permission
- Under
Apply Policy
selectOnly Bank Teller and Account Owner Policy
- Ensure that the
Decision Strategy
is set toUnanimous
- Click
Save
See Create Resource-Based Permissions
Phew...
Evaluating the Resource-Based permission
- Again under the
Authorization
tab, selectEvaluate
- Under
User
enterbob
- Under
Roles
selectuser
- This is where we will associate our user with our created roles.
- Under
Resources
selectView Account Resource
and clickAdd
- Click on Evaluate.
- Expand the
View Account Resource with scopes [account:view]
to see the results and you should seeDENY
.
- This makes sense because we only allow two roles access to that resource via the
Only Bank Teller and Account Owner Policy
. Let's test this to make sure this is true! - Click on the
Back
link right above the evaluation result - Change bob's role to
account_owner
and click onEvaluate
. You should now see the result asPERMIT
. Same deal if you go back and change the role tobank_teller
See Evaluating and Testing Policies
Create Scope-Based Permission
- Go back to the
Permissions
section - Select
Scope-Based
this time under theCreate Permission
dropdown. - Under
Name
, enterView Account Scope Permission
- Under
Scopes
, enteraccount:view
- Under
Apply Policy
, enterOnly Account Owner Policy
- Ensure that the
Decision Strategy
is set toUnanimous
- Click
Save
See Creating Scope-Based Permissions
Second test run
Evaluating our new changes
- Go back to the
Authorization
section - Click on
Evaluate
- User should be
bob
- Roles should be
bank_teller
- Resources should be
View Account Resource
and clickAdd
- Click on
Evaluate
and we should getDENY
.- Again this should come as no surprise as the
bank_teller
has access to theresource
but not thescope
. Here one permission evaluates to true, and the other to false. Given that the resource server'sDecision Strategy
is set toUnanimous
, the final decision isDENY
.
- Again this should come as no surprise as the
- Click on
Settings
under theAuthorization
tab, and change theDecision Strategy
toAffirmative
and go back to steps 1-6 again. This time, the final result should bePERMIT
(one permission is true, so final decision is true). - For the sake of completeness, turn the resource server's
Decision Strategy
back toUnanimous
. Again, go back to steps 1 through 6 but this time, set the role asaccount_owner
. This time, the final result is againPERMIT
which makes sense, given that theaccount_owner
has access to both theresource
andscope
.
Neat :) Hope this helps.
这篇关于keycloak 中的资源、范围、权限和策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 这是有道理的,因为我们只允许两个角色通过