Ory keto

690 阅读9分钟

权限服务器keto

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

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

1 代码下载

keto源码地址下载

官方文档简单说明

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

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

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

<a data-fancybox title="keto存放位置" href="/img/goImage/keto1.png">[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5g6mf68-1591890034559)(/img/goImage/keto1.png)]</a>

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修改

<a data-fancybox title="bug" href="/img/goImage/bug1.png">[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFOyCvyD-1591890034564)(/img/goImage/bug1.png)]</a>

将url.go 中的 <a data-fancybox title="bug1xxiu" href="/img/goImage/bug1xxiu.png">[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tJtz5Rl-1591890034568)(/img/goImage/bug1xxiu.png)]</a>

修改为 <a data-fancybox title="bug1xiu" href="/img/goImage/bug1xiu.png">[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCqOfDvW-1591890034572)(/img/goImage/bug1xiu.png)]</a>

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

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
>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"

3.2 启动服务

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

3.3 项目API

swagger安装教程

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

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

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

3.4 主要是要用的访问策略

ACL:

在这里插入图片描述 访问控制列表

blog_post.createblog_post.deleteblog_post.modifyblog_post.read
Aliceyesyesyesyes
Bobnononoyes
Peteryesnoyesyes

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"
}

同样:

{
  "subjects": ["alice", "bob"],
  "resources": [
    "blog_posts:my-first-blog-post",
    "blog_posts:2",
    "blog_posts:3"
  ],
  "actions": ["delete", "create", "read", "modify"],
  "effect": "allow"
}

会在数据库生成新的记录

{
  "subjects": ["peter"],
  "resources": [
    "blog_posts:my-first-blog-post",
    "blog_posts:2",
    "blog_posts:3"
  ],
  "actions": ["delete", "create", "read", "modify"],
  "effect": "deny"
}

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

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"]]
  }
}

4.3 主要请求及其说明

参数说明

响应参数说明

NameTypeRequiredRestrictionsDescription
codeinteger(int64)falsenonenone
details[object]falsenonenone
additionalPropertiesobjectfalsenonenone
messagestringfalsenonenone
reasonstringfalsenonenone
requeststringfalsenonenone
statusstringfalsenonenone

请求参数说明

ParameterInTypeRequiredDescription
flavorpathstringtrueThe 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

body

{
  "action": "string",
  "context": {
    "property1": {},
    "property2": {}
  },
  "resource": "string",
  "subject": "string"
}

4.5 参数列表

OryAccessControlPolicyAllowedInput*

NameTypeRequiredRestrictionsDescription
actionstringfalsenoneAction is the action that is requested on the resource.
contextobjectfalsenoneContext is the request's environmental context.
additionalPropertiesobjectfalsenonenone
resourcestringfalsenoneResource is the resource that access is requested to.
subjectstringfalsenoneSubject 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

参数列表

ParameterInTypeRequiredDescription
flavorpathstringtrueThe ORY Access Control Policy flavor. Can be "regex", "glob", and "exact"
limitqueryinteger(int64)falseThe maximum amount of policies returned.
offsetqueryinteger(int64)falseThe offset from where to start looking.
subjectquerystringfalseThe subject for whom the policies are to be listed.
resourcequerystringfalseThe resource for which the policies are to be listed.
actionquerystringfalseThe 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

参数列表

ParameterTypeRequiredRestrictionsDescription
actions[string]falsenoneActions is an array representing all the actions this ORY Access Policy applies to.
conditionsobjectfalsenoneConditions represents a keyed object of conditions under which this ORY Access Policy is active.
additionalPropertiesobjectfalsenonenone
descriptionstringfalsenoneDescription is an optional, human-readable description.
effectstringfalsenoneEffect is the effect of this ORY Access Policy. It can be "allow" or "deny".
idstringfalsenone访问策略的唯一标识,用来查询,更新和删除
resources[string]falsenoneResources is an array representing all the resources this ORY Access Policy applies to.
subjects[string]falsenoneSubjects 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

5.4 删除访问控制策略

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

6 访问控制策略角色操作

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

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

参数说明:

ParameterInTypeRequiredDescription
flavorpathstringtrueThe ORY Access Control Policy flavor. Can be "regex", "glob", and "exact"
limitqueryinteger(int64)falseThe maximum amount of policies returned.
offsetqueryinteger(int64)falseThe offset from where to start looking.
memberquerystringfalseThe 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

例子:

{
  "id": "string",
  "members": ["string"]
}

参数列表

ParameterTypeRequiredDescription
idstringfalseID is the role's unique id.
members[string]falseMembers is who belongs to the role.

6.3 获取访问控制角色信息

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

6.4 删除访问控制角色信息

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

6.5 为角色添加用户

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

请求体:
{
  "members": ["string"]
}

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

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

7 健康检查

7.1 检查存活状态

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

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

{  "status": "ok" }

7.2 检查准备就绪

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

7.3 获取当前版本

GET /version HTTP/1.1 
Accept: application/json

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"]
}

ation/json




## 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"] }