前言

随着人工智能、大数据和云计算的飞速发展,海量的非结构化数据需要长期存储和处理。传统的块存储技术由于存在文件共享限制和文件存储数据路径瓶颈,面临较大的挑战,而对象存储技术通过将文件数据和存储元数据管理进行分离,突破了这两大瓶颈,能更高效地保存和处理海量数据,并且在可用性,可扩展性,安全性和跨平台数据共享等方面都有着更大的优势。本文主要立足于存储服务的安全访问控制,阐述中通的文件存储服务从简单文件存储ZFS演进到对象存储的过程中是如何保障安全的。

为什么要访问控制

没有身份认证和授权,就没有信息安全。每一起数据泄露事件,调查的时候首先查的就是访问控制策略。无论是终端用户疏忽大意造成的敏感数据意外暴露,还是因为公共Web服务器软件漏洞而泄露敏感数据,访问控制都是其中关键因素。如果没有恰当实现和维护好访问控制策略,就可能会造成灾难性后果。

常见的访问控制模型

自主访问控制(DAC: Discretionary Access Control)

DAC由客体的属主对自己的客体进行管理,由属主自己决定是否将自己的客体访问权或部分访问权授予其他主体,这种控制方式是自主的。也就是说,在自主访问控制下,用户可以按自己的意愿,有选择地与其他用户共享他的文件。DAC最大缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。

图1. Windows的文件权限

强制访问控制(MAC: Mandatory Access Control)

MAC在计算机安全领域指一种由操作系统约束的访问控制,目标是限制主体或发起者访问或对对象或目标执行某种操作的能力。在实践中,主体通常是一个进程或线程,对象可能是文件、目录、TCP/UDP端口、共享内存段、I/O设备等。主体和对象各自具有一组安全属性。每当主体尝试访问对象时,都会由操作系统内核强制施行授权规则——检查安全属性并决定是否可进行访问。任何主体对任何对象的任何操作都将根据一组授权规则(也称策略)进行测试,决定操作是否允许。在数据库管理系统中也存在访问控制机制,因而也可以应用强制访问控制;在此环境下,对象为表、视图、过程等。

图2. SELinux MAC

基于角色的访问控制(RBAC: Role-Based Access Control)

RBAC基本思想是对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。这样做的好处是,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理,减少系统的开销。

图3. RBAC核心设计

基于属性的访问控制(ABAC: Attribute-Based Access Control)

不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。实现ABAC的关键标准是XACML和ALFA,要使用ABAC创建和编辑属性,需要具备XACML方面的专业知识,这使开发的成本大大增加。

图4. XACML体系结构

基于策略的访问控制(PBAC: Policy-Based Access Control)

PBAC是一种将角色和属性与逻辑结合以创建灵活的动态控制策略的方法。与ABAC一样,它使用许多属性来确定访问权限,因此它也提供了“细粒度”访问控制。PBAC旨在支持各种方式的访问设备,通常被认为是最灵活的授权解决方案。不同于ABAC的是,PBAC可以用自然语言编码,通过快速有效地定义访问权限和参数,管理人员可以实时控制和实施授权策略。

中通简单文件存储安全访问控制

在对象存储上线之前,中通简单文件存储ZFS承载了中通快递集团绝大多数非结构化数据的存储服务需求(日均上传4000W+,QPS峰值2000+)。之前在中通统一安全文件存储服务实践中有过详细的介绍。

在访问控制方面,ZFS通过中通帐号与权限系统统一管理应用维度的appid和secret,用校验密钥对签名和校验用户sso token的方式实现访问控制。这种方式保证了访问控制的安全性,但在灵活性上有所不足,应用和应用之间相互隔离,无法共享资源。例如:1. A应用想请求B应用的资源;2.C应用想把部分资源设置成公开资源。

对此我们也尝试根据RBAC设计访问控制模型,去打通应用间的壁垒。但文件存储数据路径瓶颈和以应用为中心管理密钥的方式,让我们在用户和资源维度都不能实现更细颗粒度的控制,并且即使我们重新设计出精细的访问控制模型,也很难形成一套统一的标准,这无疑会大大增加用户接入的成本。因此,拥抱行业标准的S3存储协议显得势在必行。

S3协议的三种访问控制模型

  • IAM Policy

IAM Policy是基于IAM身份(User,Group或者Role)来进行访问控制。policy作为一个对象,当与身份关联时将定义其权限,控制对S3所能做的操作。

IAM Policy由多个Statement组成,每个Statement都规定了IAM身份允许/禁止对某个资源(针对S3的控制是IAM Policy的子集)可以进行哪些操作。如下IAM Policy表示允许对名为mybucket的S3的bucket做任何s3的操作。


{

"Version":"2012-10-17",

"Statement":[

{

"Sid":"ThirdStatement",

"Effect":"Allow",

"Action":"s3:*",

"Resource":[

"arn:aws:s3:::mybucket",

"arn:aws:s3:::mybucket/*"

],

"Condition":{"Bool":{"aws:MultiFactorAuthPresent":"true"}}

}

]

}

其中Sid定义了操作statementID用以区分,Effect定义了允许/禁止,Resource定义了资源(包括但不限于S3),Action定义了哪些操作,Condition定义了在什么情况下策略授予许可。

  • Bucket Policy

Bucket Policy是基于资源bucket来进行访问控制,且只能定义本Bucket中资源的访问权限,无法定义对其他Bucket的访问权限。

Bucket Policy定义了某些身份允许/禁止对本bucket进行哪些操作。其中字段定义与IAM Policy相同。如下示例定义了所有角色对mybucket下的所有对象都有可读权限。

{

"Version":"2012-10-17",

"Statement":[

{

"Sid":"FirstStatement",

"Effect":"Allow",

"Principal":"*",

"Action":"s3:GetObject",

"Resource":"arn:aws:s3:::mybucket/*"

}

]

}

  • S3 ACL

S3 ACL也是基于资源来进行访问控制,不同的是它可以精细到具体的object,定义了哪些身份可以对哪些资源的访问控制。

AWS为ACL定义了以下权限列表:

Permission 在存储桶上授权时 在对象上授权时
READ 允许被授权者列出存储桶中的对象 允许被授权者读取对象数据及其元数据
WRITE 允许被授权者创建、覆盖和删除存储桶中的任意对象 不适用
READ_ACP 允许被授权者读取存储桶 ACL 允许被授权者读取对象 ACL
WRITE_ACP 允许被授权者为适用的存储桶编写 ACL 允许被授权者为适用的对象编写 ACL
FULL_CONTROL 允许被授权者在存储桶上的 READ、WRITE、READ_ACP 和 WRITE_ACP 许可 允许被授权者在对象上的 READ、READ_ACP 和 WRITE_ACP 许可

早期的时候,S3 ACL解决了很多对象存储在访问控制上的需求。现在可以使用IAM Policy和Bucket Policy来设置更细粒度的控制。

多个访问控制之间的判断规则

当用户访问或操作S3的资源时,S3会综合考虑IAM policy, S3 Bucket Policy和S3 ACL三者的设置,从而得出是否允许用户的操作。

总共有三种类型的Effect:

  • default Deny – 基于最小权限原则,所有的Object默认都是私有的,也就是拒绝访问的。

  • explicit Deny – 显式拒绝, IAM Policy或S3 Bucket Policy中Effect字段中显式声明为”Deny”,注意ACL中没有显示拒绝。

  • explicit Allow – 显式允许, IAM Policy或S3 Bucket policy中Effect字段中显式生命为”Allow”的,ACL中设置的允许权限也是显式允许。

整体判定规则为:

  • 当有显式拒绝时,会被判定为拒绝访问。

  • 没有显式拒绝,有显示允许时,会被判定为允许访问。

  • 没有显式拒绝也没有显示允许时,就适用默认拒绝规则,会被判定为拒绝访问。

图5. 授权过程

中通对象存储安全访问控制

由于IAM Policy和Bucket Policy已经可以实现更高颗粒度的访问控制,我们在选择上放弃了S3 ACL。

IAM Policy未来我们将接入中通零信任安全架构IAM平台。IAM允许在一个帐号下创建并管理多个身份,并允许给单个身份或一组身份分配不同的权限,从而实现不同用户拥有不同资源访问权限的目的。IAM功能特性如下:

  • 集中管理控制IAM用户及其密钥:管理每个IAM用户及其访问密钥。

  • 集中管理控制IAM用户的访问权限:控制每个IAM用户访问资源的权限。

  • 集中管理控制IAM用户的资源访问方式:确保IAM用户在指定的时间和网络环境下,通过安全信道访问特定的对象存储资源。

  • 集中管理控制对象存储资源:对IAM用户创建的实例或数据进行集中控制。当用户离开组织时,实例或数据不会丢失。

Bucket Policy则由底层ZTO OSS服务实现。为了方便用户使用,我们内置了3种Bucket Policy,分别代表公有读、公有读写和私有。

读写权限

  • 公有读(public-read)

{
"Statement":[

{

"Action":[

"s3:GetBucketLocation",

"s3:ListBucket"

],

"Effect":"Allow",

"Principal":"*",

"Resource":[

"arn:aws:s3:::mybucket"

]

},

{

"Action":[

"s3:GetObject"

],

"Effect":"Allow",

"Principal":"*",

"Resource":[

"arn:aws:s3:::mybucket/*"

]

}

],

"Version":"2012-10-17"

}

  • 公有读写(public-readwrite)

{

"Statement":[

{

"Action":[

"s3:GetBucketLocation",

"s3:ListBucket",

"s3:ListBucketMultipartUploads"

],

"Effect":"Allow",

"Principal":"*",

"Resource":[

"arn:aws:s3:::mybucket"

]

},

{

"Action":[

"s3:AbortMultipartUpload",

"s3:DeleteObject",

"s3:GetObject",

"s3:ListMultipartUploadParts",

"s3:PutObject"

],

"Effect":"Allow",

"Principal":"*",

"Resource":[

"arn:aws:s3:::mybucket/*"

]

}

],

"Version":"2012-10-17"

}
  • 私有(private)

{

"Statement":[],

"Version":"2012-10-17"

}

通过管理控制台我们可以轻松的设置bucket的访问控制读写权限,同时也可以通过命令行工具进行更精细的访问控制设置。

图片6. 控制台

跨域控制

除了读写权限以外,我们基于bucket policy在跨域控制和IP白名单限制上也实现了灵活的配置规则,用户可以调用API或者命令行工具进行操作。


{

"CORSRules":[

{

"AllowedOrigins":["http://www.MY_DOMAIN_NAME","http://*.example.com"],

"AllowedHeaders":["*"],

"AllowedMethods":["GET","HEAD","POST","PUT","DELETE"],

"MaxAgeSeconds":3000,

"ExposeHeaders":["Etag"]

}

]

}

其中AllowedOrigins表示用户允许跨源资源共享访问的源地址,其最多含有一个”*”通配符。每一条 CORSRule 必须定义至少一个源地址和一种方法。例如:”http://*.example.com”。另外,你可以直接使用”*”通配符来代表全部源。

AllowedHeaders指明在预检OPTION中通过 Access-Control-Request-Headers 哪些头部是可以使用的。每一个在Access-Control-Request-Headers中指定的头部必须要与发送到KS3请求的头部保持一致,最多使用一个”*”通配符。

AllowedMethods表示用户允许源所能执行的HTTP方法,每一条 CORSRule 必须定义至少一个源地址和一种方法。

MaxAgeSeconds指定在KS3针对特定资源的预检OPTIONS请求作出响应后,浏览器缓存该响应的时间。一个CORSRule最多有一个 MaxAgeSeconds 元素。

ExposeHeader识别可允许客户从应用程序(例如,从JavaScriptXMLHttpRequest数据元)进行访问的响应标头。

IP白名单

我们将通过设置IAM Policy和Bucket Policy的Condition字段分别从身份和资源两个维度限制remote ip的访问权限,进行精细的ip白名单控制。如下policy示例表示10.9.36.*和192.168.65.*网段限制访问。

{

"Version":"2012-10-17",

"Statement":{

"Effect":"Deny",

"Action":"*",

"Resource":"*",

"Condition":{

"NotIpAddress":{

"aws:SourceIp":[

"10.9.36.0/24",

"192.168.65.0/16"

]

}

}

}

}

结语

目前我们已经基于bucket Policy实现了灵活的访问控制,API也已全部兼容S3协议。接下来我们将全面接入中通零信任IAM,实现更丰富的访问控制功能,中通零信任IAM玩法灵活,用户可以根据自己的需求实现不同颗粒度的安全访问控制。未来我们还将在数据安全性、混合云支持、多租户支持、容器支持、包括块存储在内的混合存储支持、跨境传输速度、跨区域复制、冷热分离,异地容灾等方面持续优化,提供更安全优质的数据存储私有云服务。

作者简介

刘易,中通快递信息安全部开发工程师,负责中通安全文件存储和对象存储服务的开发维护。关于安全存储的问题,欢迎大家交流探讨。

相关参考

AWS IAM实践:

https://aws.amazon.com/iam

PBAC相对于传统ABAC的优势:

https://blog.plainid.com/the-advantage-of-pbac-over-the-traditional-abac

阿里云OSS ACL设置:

https://help.aliyun.com/document_detail/52284.html

访问控制-维基百科:

https://en.wikipedia.org/wiki/Computer_access_control

SELinux MAC:

https://www.incibe-cert.es/en/blog/selinux-and-mac

中通安全团队团队介绍

中通信息安全团队是一个年轻、向上、踏实以及为梦想而奋斗的大家庭,我们的目标是构建一个基于海量数据的全自动信息安全智能感知响应系统及管理运营平台。我们致力于支撑中通快递集团生态链全线业务(快递、快运、电商、传媒、金融、航空等)的安全发展。我们的技术路线紧跟业界发展,从大前端到云原生、从大数据到机器学习、从DevSecOps到零信任安全架构都有涵盖。全球日均件量最大快递公司的数据规模也将是一个非常大的挑战。我们关注的方向除了国内一线互联网公司外,也关注 Google、Facebook、Amazon 等在基础安全、数据安全方面的实践。

声明:本文来自中通安全应急响应中心,版权归作者所有。文章内容仅代表作者独立观点,不代表士冗科技立场,转载目的在于传递更多信息。如有侵权,请联系 service@expshell.com。