# 权限服务器keto

keto介绍

ORY Keto是一种权限服务器,它实现最佳实践访问控制机制:

  • 今天可用:具有精确,全局和正则表达式匹配策略的ORY风格的访问控制策略
  • 即将推出:
  • 访问控制列表
  • 基于角色的访问控制
  • 具有上下文的基于角色的访问控制(Google / Kubernetes风格)
  • Amazon Web Services身份和访问管理策略(AWS IAM策略)
  • 每种机制都由在开放策略代理之上实现的决策引擎提供动力,并提供定义明确的管理和授权端点

# 1 代码下载

keto源码地址下载

官方文档简单说明

解压说明

把下载的源码解压后放在本地%GOPATH%/src目录下

注:GOPATH为项目的运行时的工作空间位置,GOPATH其中包含三个子目录如下

  • src 目录包含Go的源文件,它们被组织成包(每个目录都对应一个包)
  • pkg 目录包含包对象
  • bin 目录包含可执行命令

keto存放位置

# 2 关键词介绍

# 2.1 RBAC

RBAC介绍

​RBAC是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。 。RBAC 认为授权实际上是WhoWhatHow 三元组之间的关系,也就是WhoWhat 进行How 的操作,也就是“主体”对“客体”的操作。 然后 RBAC 又分为RBAC0、RBAC1、RBAC2、RBAC3 ,如果你不知道他们有什么区别,你可以百度百科:百度百科-RBAC ,也可以看看我的介绍。

  • Who:是权限的拥有者或主体(如:User,Role)。
  • What:是操作或对象(operation,object)。
  • How:具体的权限(Privilege,正向授权与负向授权)。

# 2.1 ABAC

ABAC介绍

ABAC(Attribute Base Access Control) 基于属性的权限控制,不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。 访问控制列表(**ACL **)是一种基于包过滤的访问控制技术,它可以根据设定的条件对接口上的数据包进行过滤,允许其通过或丢弃。访问控制列表被广泛地应用于路由器和三层交换机,借助于访问控制列表,可以有效地控制用户对网络的访问,从而最大程度地保障网络安全。

# 2.3 采坑bug修改

bug

将url.go 中的 bug1xxiu

修改为 bug1xiu

这个问题存在是由于应用源码对字符串的解析问题,可以不写端口,采用默认的端口

# 3 项目运行

官方代码下载后编译成keto.exe执行,直接执行指挥出现提示页面

# 3.1 代码示例

dsn: mysql://root:minda123@tcp(127.0.0.1)/keto?parseTime=true&multiStatements=true 
# 这里如果用默认端口就不要加端口号:3306

secrets:
  system:
    - admin1
    - admin2
    - admin3
1
2
3
4
5
6
7
8
>keto.exe --config F:/awesomeProject/bin/config.yaml migrate sql -e
      
time="2019-12-25T16:27:28+08:00" level=info msg="Connecting with mysql://*:*@tcp(127.0.0.1)/keto?multiStatements=true"
time="2019-12-25T16:27:28+08:00" level=info msg="Connected to SQL!"
time="2019-12-25T16:27:28+08:00" level=info msg="Applying storage SQL migrations..."
time="2019-12-25T16:27:28+08:00" level=info msg="Successfully applied SQL migrations" applied_migrations=1 migration=name
time="2019-12-25T16:27:28+08:00" level=info msg="Done applying storage SQL migrations"

1
2
3
4
5
6
7
8

# 3.2 启动服务

serve --config F:/awesomeProject/bin/config.yaml
1

# 3.3 项目API

swagger安装教程

进入项目根目录,启动swagger服务

swagger serve -F=swagger F:\awesomeProject\src\github.com\ory\keto\docs\api.swagger.json
1

运行成功后会提示服务运行在的地址,点击进入即可看到如下页面: canvas

# 3.4 主要是要用的访问策略

# ACL:

访问控制列表

blog_post.create blog_post.delete blog_post.modify blog_post.read
Alice yes yes yes yes
Bob no no no yes
Peter yes no yes yes

# RBAC:

RBAC

# 4 ORY Access Control Policies

# 4.1 策略准备

put请求:http://127.0.0.1:4444//engines/acp/ory/glob/policies

{
  "subjects": ["alice"],
  "resources": ["blog_posts:my-first-blog-post"],
  "actions": ["delete"],
  "effect": "allow"
}
1
2
3
4
5
6

同样:

{
  "subjects": ["alice", "bob"],
  "resources": [
    "blog_posts:my-first-blog-post",
    "blog_posts:2",
    "blog_posts:3"
  ],
  "actions": ["delete", "create", "read", "modify"],
  "effect": "allow"
}
1
2
3
4
5
6
7
8
9
10

会在数据库生成新的记录

{
  "subjects": ["peter"],
  "resources": [
    "blog_posts:my-first-blog-post",
    "blog_posts:2",
    "blog_posts:3"
  ],
  "actions": ["delete", "create", "read", "modify"],
  "effect": "deny"
}
1
2
3
4
5
6
7
8
9
10

The : is a delimiter in ORY Access Control Policies. Other supported syntax is:

single symbol wildcard: ?at matches cat and bat but not at wildcard: foo:*:bar matches foo:baz:bar and foo:zab:bar but not foo:bar nor foo:baz:baz:bar super wildcard: foo:**:bar matches foo:baz:baz:bar, foo:baz:bar, and foo:bar, but not foobar or foo:baz character list: [cb]at matches cat and bat but not mat nor at. negated character list: [!cb]at matches tat and mat but not cat nor bat. ranged character list: [a-c]at cat and bat but not mat nor at. negated ranged character list: [!a-c]at matches mat and tat but not cat nor bat. alternatives list: {cat,bat,[mt]at} matches cat, bat, mat, tat and nothing else. backslash: foo\\bar matches foo\bar and nothing else. foo\bar matches foobar and nothing else. foo\*bar matches foo*bar and nothing else. Please note that when using JSON you need to double escape backslashes: foo\\bar becomes {"...": "foo\\\\bar"}.

The pattern syntax is:

  pattern:

      { term }

  term:

      *         matches any sequence of non-separator characters

      **        matches any sequence of characters

      ?         matches any single non-separator character

      [ [ ! ] { character-range } ]

                  character class (must be non-empty)

      { pattern-list }

                  pattern alternatives

      c           matches character c (c != *, **, ?, \, [, {, })

      \ c       matches character c

  character-range:

      c           matches character c (c != \\, -, ])

      \ c       matches character c

      lo - hi   matches character c for lo <= c <= hi

  pattern-list:

      pattern { , pattern }

                  comma-separated (without spaces) pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 4.2 json实例

{
  "description": "One policy to rule them all.",
  "subjects": ["users:maria:*"],
  "actions": ["delete", "create", "update","modify","get","read"],
  "effect": "allow",
  "resources": ["resources:articles:<.*>"],
  "conditions": {
    "someKeyName": {
      "type": "StringMatchCondition",
      "options": {
        "matches": "foo.+"
      }
    },
    "someKey": {
      "type": "StringPairsEqualCondition",
      "options": {}
    }, 
    "myKey": {
      "type": "StringEqualCondition",
      "options": {
        "equals": "expected-value"
      }
    },      
    "remoteIPAddress": {
      "type": "CIDRCondition",
      "options": {
        "cidr": "192.168.0.0/16"
      }
    },
    "this-key-will-be-matched-with-the-context": {
      "type": "SomeConditionType",
      "options": {
        "some": "configuration options set by the condition type"
      }
    }
  },
   "context": {
    "someKey": [["foo", "foo"], ["bar", "bar"]]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 4.3 主要请求及其说明

# 参数说明

# 响应参数说明

Name Type Required Restrictions Description
code integer(int64) false none none
details [object] false none none
additionalProperties object false none none
message string false none none
reason string false none none
request string false none none
status string false none none

# 请求参数说明

Parameter In Type Required Description
flavor path string true The ORY Access Control Policy flavor. Can be "regex", "glob", and "exact".

# 4.4 检查请求是否允许通过

请求头

POST /engines/acp/ory/{flavor}/allowed HTTP/1.1

Content-Type: application/json

Accept: application/json

1
2
3
4
5
6

body

{
  "action": "string",
  "context": {
    "property1": {},
    "property2": {}
  },
  "resource": "string",
  "subject": "string"
}
1
2
3
4
5
6
7
8
9

# 4.5 参数列表

OryAccessControlPolicyAllowedInput*

Name Type Required Restrictions Description
action string false none Action is the action that is requested on the resource.
context object false none Context is the request's environmental context.
additionalProperties object false none none
resource string false none Resource is the resource that access is requested to.
subject string false none Subject is the subject that is requesting access.

response

{"allowed":"true"} or {"allowed":"false"}

# 5 访问控制策略操作

# 5.1 获取访问控制策略集合

GET /engines/acp/ory/{flavor}/policies HTTP/1.1
Accept: application/json
1
2

参数列表

Parameter In Type Required Description
flavor path string true The ORY Access Control Policy flavor. Can be "regex", "glob", and "exact"
limit query integer(int64) false The maximum amount of policies returned.
offset query integer(int64) false The offset from where to start looking.
subject query string false The subject for whom the policies are to be listed.
resource query string false The resource for which the policies are to be listed.
action query string false The action for which policies are to be listed.

# 5.2 更新访问控制策略

PUT /engines/acp/ory/{flavor}/policies HTTP/1.1
Content-Type: application/json
Accept: application/json
1
2
3

参数列表

Parameter Type Required Restrictions Description
actions [string] false none Actions is an array representing all the actions this ORY Access Policy applies to.
conditions object false none Conditions represents a keyed object of conditions under which this ORY Access Policy is active.
additionalProperties object false none none
description string false none Description is an optional, human-readable description.
effect string false none Effect is the effect of this ORY Access Policy. It can be "allow" or "deny".
id string false none 访问策略的唯一标识,用来查询,更新和删除
resources [string] false none Resources is an array representing all the resources this ORY Access Policy applies to.
subjects [string] false none Subjects is an array representing all the subjects this ORY Access Policy applies to.

# 5.3 查询具体的策略

GET /engines/acp/ory/{flavor}/policies/{id} HTTP/1.1
Accept: application/json
1
2

# 5.4 删除访问控制策略

DELETE /engines/acp/ory/{flavor}/policies/{id} HTTP/1.1
Accept: application/json
1
2

# 6 访问控制策略角色操作

# 6.1 查询寻访问控制角色集合

GET /engines/acp/ory/{flavor}/roles HTTP/1.1
Accept: application/json
1
2

参数说明:

Parameter In Type Required Description
flavor path string true The ORY Access Control Policy flavor. Can be "regex", "glob", and "exact"
limit query integer(int64) false The maximum amount of policies returned.
offset query integer(int64) false The offset from where to start looking.
member query string false The member for which the roles are to be listed.

# 6.2 添加访问控制的角色

PUT /engines/acp/ory/{flavor}/roles HTTP/1.1
Content-Type: application/json
Accept: application/json

1
2
3
4

例子:

{
  "id": "string",
  "members": ["string"]
}
1
2
3
4

参数列表

Parameter Type Required Description
id string false ID is the role's unique id.
members [string] false Members is who belongs to the role.

# 6.3 获取访问控制角色信息

GET /engines/acp/ory/{flavor}/roles/{id} HTTP/1.1
Accept: application/json
1
2

# 6.4 删除访问控制角色信息

DELETE  /engines/acp/ory/{flavor}/roles/{id} HTTP/1.1
Accept: application/json
1
2

# 6.5 为角色添加用户

PUT /engines/acp/ory/{flavor}/roles/{id}/members HTTP/1.1 Content-Type: application/json Accept: application/json

请求体:
{
  "members": ["string"]
}
1
2
3
4
5
6

# 6.6从角色中删除某个用户成员

DELETE /engines/acp/ory/{flavor}/roles/{id}/members/{member} HTTP/1.1 Accept: application/json
1

# 7 健康检查

# 7.1 检查存活状态

GET /health/alive HTTP/1.1
Accept: application/json
1
2

结果:(官方说明总是ok)

{  "status": "ok" }
1

# 7.2 检查准备就绪

GET /health/ready HTTP/1.1
Accept: application/json
1
2

# 7.3 获取当前版本

GET /version HTTP/1.1 
Accept: application/json
1
2

# 8 测试样例

put   http://127.0.0.1:4444/engines/acp/ory/glob/policies

{
  "actions": ["get","create","modify","delete"],
  "conditions": {
    "optionAccess": {
    	"type": "CIDRCondition",
    	"options": {
        "cidr": "192.168.0.0/16"
      }
    }
  },
  "description": "test q",
  "effect": "allow",
  "id": "string",
  "resources": [ 
  	"blog_posts:my-first-blog-post",
    "blog_posts:2",
    "blog_posts:3"],
  "subjects": ["admin","admin1","admin2"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21