访问控制模型
项目中需要加入访问控制,对访问控制模型做了一些调研, 本文主要是介绍一些常用的访问控制模型。
基本要素
访问控制模型包括三个要素,即:
-
主体(Subject) 指主动对其它实体施加动作的实体
-
客体(Object) 是被动接受其他实体访问的实体
-
控制策略(Policy)为主体对客体的操作行为和约束条件
安全策略
主体、客体,控制策略三者需要满足的基本安全策略:
-
最小特权原则:给主体分配权限时要遵循权限最小化原则,最小特权原则的优点是最大限度地限制了主体实施授权行为,可以避免来自突发事件、错误和未授权用主体的危险。
-
最小泄漏原则:它是指主体执行任务时,按照主体所需要知道的信息最小化的原则分配给主体权利。也就是要保护敏感信息不要被无关人员知道,别人知道得越少越好。
-
多级安全策略:多级安全策略是指主体和客体间的数据流向和权限控制按照安全级别的绝密(TS)、秘密(S)、机密(C)、限制(RS)和无级别(U)五级来划分。多级安全策略的优点是避免敏感信息的扩散,只有安全级别比他高的主体才能够访问。
发展
1985年美国军方提出可信计算机系统评估准则TCSE,描述了两种著名的访问控制策略,自主访问控制模型(DAC)和强制访问控制模型(MAC)。基于角色的访问控制模型(RBAC)在1992年被提出。基于属性的访问控制模型(ABAC)则被认为是访问控制模型的未来。
自主访问控制模型(DAC)
自主访问控制模型(DAC,Discretionary Access Control)是根据自主访问控制策略建立的一种模型,允许合法用户以用户或用户组的身份访问策略规定的客体,同时阻止非授权用户访问客体。拥有客体权限的用户,可以将该客体的权限分配给其他用户。例如没有文件File1访问权限的用户可以从有访问权限的B用户那里得到访问权限。
DAC访问控制的实现
权限控制列表(ACL)
访问控制列表(ACL, Access Control List),每一个客体都配有一个列表,这个列表记录了主体对客体进行何种操作。当系统试图访问客体时,先检查这个列表中是否有关于当前用户的访问权限。ACL是一种面向资源的访问控制模型,它的机制是围绕资源展开的。
对于一个文件对象的ACL:
- Alice: read,write
- Bob: read
表示Alice可以对该文件进行读写操作,Bob只能读取。
权限控制矩阵(ACM)
访问控制矩阵(ACM,Access Control Matrix)是通过矩阵形式描述主体和客体之间的权限分配关系。每个主体而言,都拥有对哪些客体的哪些访问权限;而对客体而言,又有哪些主体对他可以实施访问;
Asset 1 | Asset 2 | File | Device | |
---|---|---|---|---|
Role 1 | read, write, execute, own | execute | read | write |
Role 2 | read | read, write, execute, own |
DAC应用场景
DAC常见于文件系统,LINUX,UNIX、WindowsNT版本的操作系统都提供DAC的支持。在实现上,先对用户鉴权,然后根据控制列表决定用户能否访问资源。用户控制权限的修改通常由特权用户或者管理员组实现。DAC最大缺陷就是对权限控制比较分散,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。主体的权限太大,无意间就可能泄露信息。
强制访问控制模型(MAC)
强制访问控制模型(MAC, Mandatory Access Control),是为了弥补DAC权限控制过于分散的问题而诞生的。
- Subject被赋予一定的安全级别
- Object被赋予一定的安全级别
- Subject能否访问Object由双方的关系安全级别决定,这个判断通常有系统硬性限制
MAC非常适合机密机构或者其他等级观念强烈的行业,过重强调保密性,管理不够灵活。在实现上,MAC和DAC通常为每个用户赋予对客体的访问权限规则集,考虑到管理的方便,在这一过程中还经常将具有相同职能的用户聚为组,然后再为每个组分配许可权。
基于角色的访问控制(RBAC)
基于角色的访问控制(RBAC, Role Based Access Control)在用户和权限之间引入了“角色(Role)”的概念,角色解耦了用户和权限之间的关系。
角色和组的主要区别:
- 组是用户的集合
- 角色是权限的集合
- 角色/权限之间的变化比组/用户关系之间的变化相对要慢得多,减小了授权管理的复杂性
RBAC0
RBAC0作为基础模型,只包含核心的三要素,用户,角色,权限。用户和角色可以是多对多的关系,权限和角色也是多对多的关系。
RBAC1
RBAC1包括了RBAC0并且添加了角色继承。顾名思义,角色继承就是指角色可以继承于其他角色,在拥有其他角色权限的同时,自己还可以关联额外的权限。这种设计可以给角色分组和分层,一定程度简化了权限管理工作。也就是角色之间存在上下级的关系,对应到实体设计中也就是角色实体的自身关联。
RBAC2
RBAC2也包括RBAC0并且添加了约束。RBAC1和RBAC2相互独立.
RBAC2的约束规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。
- 互斥约束:包括互斥用户,互斥角色,互斥权限。同一个用户不能拥有相互排斥的角色,两个互斥角色不能分配一样的权限集,互斥的权限不能分配给同一个角色,在session中,同一个角色不能拥有互斥权限。
- 基数约束:一个角色被分配的用户数量受限,它指的是有多少用户能拥有这个角色。例如:一个角色专门为公司CEO创建的,那这个角色的数量是有限的。
- 先决条件角色:指要想获得较高的权限,要首先拥有低一级的权限。例如:先有副总经理权限,才能有总经理权限。
RBAC3
RBAC3是一个全功能的RBAC,RBAC3合并了RBAC0,RBAC1,RBAC2.
基于属性的访问控制(ABAC)
基于属性的访问控制(ABAC, Attribute Based Access Control)通过动态计算一个或一组属性是否满足某种条件来进行授权判断。可以按需实现不同颗粒度的权限控制,但定义权限时不易看出用户和对象间的关系。如果规则复杂,容易给管理者带来维护和追查带来麻烦。
属性通常来说分为四类:
- 用户属性(如用户年龄)
- 环境属性(如当前时间)
- 操作属性(如读取)
- 对象属性(如一篇文章,又称资源属性)
跟RBAC相比,ABAC对权限的控制粒度更细,如控制用户的访问速率。实际开发中可以结合RBAC角色管理的优点和ABAC的灵活性一起使用。
用ABAC控制访问速率
package main
import (
"fmt"
"strconv"
"github.com/casbin/casbin"
"github.com/casbin/casbin/model"
)
type Request struct {
Subject string
Object string
Action string
Count int
}
func (r Request) IsBelow(limit string) bool {
a, err := strconv.Atoi(limit)
if err != nil {
return false
}
fmt.Printf("%d < %d %v\n", r.Count, a, r.Count < a)
return r.Count < a
}
func main() {
const modelText = `
[request_definition]
r = sub, obj, act, count
[policy_definition]
p = sub, obj, act, limit
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub==p.sub && r.obj==p.obj && r.act==p.act && r.count.IsBelow(p.limit)
`
m := model.Model{}
m.LoadModelFromText(modelText)
e, _ := casbin.NewEnforcer(m)
// 添加策略
// 限制john访问http_api的次数在500次以下
e.AddPolicy("john", "http_api", "visit", "500")
// john当前访问http_api的次数为90次
request := Request{
Subject: "john",
Object: "http_api",
Action: "visit",
Count: 90}
pass, err := e.Enforce(request.Subject, request.Object, request.Action, request)
fmt.Println(pass, err)
}