企业上云首当其冲的就是要考量安全性的问题。为了保证系统的安全,和数据的安全,公司必须制定访问控制策略。首先看看现在的云平台对于身份认证与访问控制的设计。
Microsoft Azure
Azure 资源的基于角色的访问控制 (RBAC)
Role-Based Access Control :其基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。
RBAC 的作用示例
- 让一个用户管理订阅中的虚拟机,另一个用户管理虚拟网络
- 让 DBA 组管理订阅中的 SQL 数据库
- 让某个用户管理资源组中的所有资源,例如虚拟机、网站和子网
- 允许某个应用程序访问资源组中的所有资源
Azure提到使用RBAC的最佳做法是授予用户完成工作所需的最低权限。使用 RBAC,可以在团队中实现职责分离,仅向用户授予执行作业所需的访问权限。 无需向每个人授予 Azure 订阅或资源的无限制权限,可以仅允许在特定的范围执行某些操作。
RBAC 的工作原理
RBAC 控制资源访问权限的方式是创建角色分配。角色分配包含三个要素:安全主体(Security Principal)、角色定义(Role Definition)和范围(Scope)。
安全主体(Security Principal)
安全主体是一个对象,表示请求访问 Azure 资源的用户、组、服务主体或托管标识。
image.png
- 用户(User) - 在 Azure Active Directory 中具有配置文件的人员。
- 组(Group) - 在 Azure Active Directory 中创建的一组用户。 将某个角色分配到某个组时,该组中的所有用户都拥有该角色。
- 服务主体(Service principal) - 应用程序或服务用来访问特定 Azure 资源的安全标识。 可将服务主体视为应用程序的用户标识(用户名和密码或证书)。
- 托管标识(Managed identity) - Azure Active Directory 中由 Azure 自动托管的标识。 在开发云应用程序时,通常使用托管标识来管理用于向 Azure 服务进行身份验证的凭据。
角色定义(Role Definition)
角色定义是权限的集合。角色定义列出可以执行的操作,例如读取、写入和删除。
Azure 包含多个可用的内置角色。分别拥有相应的权限。例如下面四个基本的内置角色。
范围(Scope)
Example角色分配是出于授予访问权限的目的,将角色定义附加到特定范围内的用户、组、服务主体或托管标识的过程。 通过创建角色分配来授予访问权限,通过删除角色分配来撤销访问权限。
下图显示了角色分配的示例。 在此示例中,为“营销”组分配了医药销售资源组的参与者角色。 这意味着,“营销”组中的用户可以在医药销售资源组中创建或管理任何 Azure 资源。
ExampleRBAC 是一个加法模型,生效的权限是角色分配相加。其中在订阅范围内向用户授予了“参与者”角色,并且授予了对资源组的“读者”角色。 “参与者”权限与“读者”权限相加实际上是资源组的“参与者”角色。 因此,在这种情况下,“读者”角色分配没有任何影响。
更加重要是Azue RBAC是如何确定用户是否有权限访问资源
步骤:
- 用户(或服务主体)获取 Azure 资源管理器的令牌。令牌包含用户的组成员身份(包括可传递的组成员身份)。
- 用户使用附加的令牌对 Azure 资源管理器发出 REST API 调用。
- Azure 资源管理器检索适用于对其执行操作的资源的所有角色分配和拒绝分配。
- Azure 资源管理器缩小适用于此用户或其组的角色分配范围,并确定用户针对此资源拥有的角色。
- Azure 资源管理器确定 API 调用中的操作是否包含在用户针对此资源拥有的角色中。
- 如果用户在请求的范围内没有具有该操作的角色,则不授予访问权限。 否则,Azure 资源管理器会检查是否适用拒绝分配。
- 如果拒绝分配适用,则阻止访问。 否则授予访问权限。
阿里云
访问控制(RAM)
访问控制(Resource Access Management)是阿里云提供的管理用户身份与资源访问权限的服务。RAM也是按需为用户分配最小权限。
RAM的功能特性如下:
- 集中控制RAM用户及其密钥:管理每个RAM用户及其访问密钥,为用户绑定多因素认证(MFA)设备。
- 集中控制RAM用户的访问权限:控制每个RAM用户访问资源的权限。
- 集中控制RAM用户的资源访问方式:确保RAM用户在指定的时间和网络环境下,通过安全信道访问特定的阿里云资源。
- 集中控制云资源:对RAM用户创建的实例或数据进行集中控制。当用户离开组织时,实例或数据不会丢失。
- 单点登录管理(SSO):支持与企业身份提供商(IdP)进行用户SSO或角色SSO。
RAM 的工作原理
RAM的主要要素是RAM用户,用户组,RAM角色。
RAM用户
RAM用户是RAM中的一种身份,对应某一个操作实体(运维操作人员或应用程序)。通过创建新的RAM用户并授权,RAM用户便可以访问相关资源。有确定的身份ID和身份凭证,它通常与某个确定的人或应用程序一一对应。
-
用户管理与分权
当企业有多种云资源时,使用RAM的身份管理与权限管理功能,实现用户分权及资源统一管理。
用户管理与分权
用户组
若云账号下有多个RAM用户,通过创建用户组对职责相同的RAM用户进行分类并授权,从而更好的管理用户及其权限。
RAM角色
RAM角色有确定的身份,可以被赋予一组权限策略,但没有确定的登录密码或访问密钥。RAM角色需要被一个受信的实体用户扮演,扮演成功后实体用户将获得RAM角色的安全令牌,使用这个安全令牌就能以角色身份访问被授权的资源。
-
角色ARN(Role ARN)
ARN是角色的全局资源描述符,用来指定具体角色。ARN遵循阿里云ARN的命名规范。例如,某个云账号下的devops角色的ARN为:acs:ram::123456789012****:role/samplerole。 -
可信实体(Trusted entity)
角色的可信实体是指可以扮演角色的实体用户身份。创建角色时必须指定可信实体,角色只能被受信的实体扮演。可信实体可以是受信的阿里云账号、受信的阿里云服务或身份提供商。 -
权限策略(Policy)
image.png
一个角色可以绑定一组权限策略。没有绑定权限策略的角色也可以存在,但不能访问资源。
RAM中权限策略的语法和结构 可以自己查看
其中权限策略结构包括:版本号,授权语句列表。每条授权语句包括授权效力(Effect)、操作(Action)、资源(Resource)以及限制条件(Condition,可选项)。
权限策略模型可以分为两种:
云账号内授权模型
image.png
资源组内授权模型
image.png -
扮演角色(Assume role)
扮演角色是实体用户获取角色身份的安全令牌的方法。一个实体用户调用STS API AssumeRole可以获得角色的安全令牌,使用安全令牌可以访问云服务API。 -
角色令牌(Role token)
角色令牌是角色身份的一种临时访问密钥。角色身份没有确定的访问密钥,当一个实体用户要使用角色时,必须通过扮演角色来获取对应的角色令牌,然后使用角色令牌来调用阿里云服务API。
RAM角色的使用方法
-
RAM角色指定可信实体,即指定可以扮演角色的实体用户身份。
-
RAM角色基本概念
说明 扮演角色是实体用户获取RAM角色令牌的方法,角色令牌是角色身份的一种临时访问凭证,使用角色令牌可以访问阿里云资源。 -
为RAM角色绑定权限策略
说明 一个RAM角色可以绑定一组权限策略,没有绑定权限策略的角色也可以存在,但不能访问资源。
-
受信实体通过扮演角色,使用角色令牌访问阿里云资源。
可以看出Azure 与阿里云 实现访问控制的模型上大同小异
访问控制身份认证实现
阿里云
阿里云的访问控制:单点登录(SSO),开放授权管理(OAuth);
点击可以参考 SSO 和 OAuth 原理
无论哪种方式登录的API,RAM服务会对每个访问的请求进行身份验证,无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。
RAM计算签名
RAM通过使用AccessKey ID和AccessKeySecret进行对称加密的方法来验证请求的发送者身份。AccessKey ID和AccessKeySecret由阿里云颁发给访问者,其中AccessKey ID用于标识访问者的身份,AccessKeySecret用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。API网关计算签名例子
计算签名可以
- 校验请求参数是否被篡改。
- 请求来源是否合法。
- 请求是否具有唯一性。
它要求调用方按照约定好的算法生成签名字符串,作为请求的一部分,接口提供方验算签名即可知是否合法。
那么如果一个系统也要实现计算签名该怎么做呢?
主要步骤:
- 接口提供方给出appKey和appSecret
- 调用方根据appId和appSecret以及请求参数,按照一定算法生成签名sign
- 接口提供方验证签名
生成签名的步骤如下:
1.将所有业务请求参数按字母先后顺序排序
2.参数名称和参数值链接成一个字符串A
3.在字符串A的首尾加上appSecret组成一个新字符串B
4.对字符串进行HmacSHA256得到签名sign
5.使用Base64生产签名字符串
看看阿里云API网关设置的签名的元素有哪些
系统级 Header
【必选】X-Ca-Key:AppKey。
【必选】X-Ca-Signature:签名字符串。
【可选】X-Ca-Timestamp:API 调用者传递时间戳,值为当前时间的毫秒数,也就是从1970年1月1日起至今的时间转换为毫秒,时间戳有效时间为15分钟。(保证请求的唯一性)
【可选】X-Ca-Nonce:API 调用者生成的 UUID,结合时间戳防重放。
【可选】Content-MD5 当请求 Body 非 Form 表单时,可以计算 Body 的 MD5 值传递给云网关进行 Body MD5 校验。(防止内容别篡改)
【可选】X-Ca-Stage请求 API 所属 Stage,目前仅支持 TEST 、PRE 和 RELEASE,默认RELEASE,若您调用的 API 不在线上环境,请一定要指定该参数的值,否则会报 URL 错误。
Example:
httpget
public static Response httpGet(String host, String path, int connectTimeout, Map<String, String> headers, Map<String, String> querys, List<String> signHeaderPrefixList, String appKey, String appSecret)
throws Exception {
headers = initialBasicHeader(HttpMethod.GET, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret);
HttpClient httpClient = wrapClient(host);
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout));
HttpGet get = new HttpGet(initUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
get.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue()));
}
return convert(httpClient.execute(get));
}
initialBasicHeader
private static Map<String, String> initialBasicHeader(String method, String path,
Map<String, String> headers,
Map<String, String> querys,
Map<String, String> bodys,
List<String> signHeaderPrefixList,
String appKey, String appSecret)
throws MalformedURLException {
if (headers == null) {
headers = new HashMap<String, String>();
}
headers.put(SystemHeader.X_CA_TIMESTAMP, String.valueOf(new Date().getTime()));
//headers.put(SystemHeader.X_CA_X_CA_TIMESTAMPNONCE, UUID.randomUUID().toString());
headers.put(SystemHeader.X_CA_KEY, appKey);
headers.put(SystemHeader.X_CA_SIGNATURE,
SignUtil.sign(appSecret, method, path, headers, querys, bodys, signHeaderPrefixList));
return headers;
}
sign
public static String sign(String secret, String method, String path,
Map<String, String> headers,
Map<String, String> querys,
Map<String, String> bodys,
List<String> signHeaderPrefixList) {
try {
Mac hmacSha256 = Mac.getInstance(Constants.HMAC_SHA256);
byte[] keyBytes = secret.getBytes(Constants.ENCODING);
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, Constants.HMAC_SHA256));
hmacSha256.
return new String(Base64.encodeBase64(
hmacSha256.doFinal(buildStringToSign(method, path, headers, querys, bodys, signHeaderPrefixList)
.getBytes(Constants.ENCODING))),
Constants.ENCODING);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
从而进行计算签名
那么后端如何校验签名呢?
主要步骤如下:
- 得到请求方携带的API签名。
- 将所有业务请求参数按字母先后顺序排序。
- 参数名称和参数值链接成一个字符串A。
- 在字符串A的首尾加上apiSecret接口密匙组成一个新字符串B。
- 对新字符串B进行HMAC_SHA256散列运算生成服务器端的API签名,将客户端的API签名进行Base64解码,然后开始验证签名。
- 如果服务器端生成的API签名与客户端请求的API签名是一致的,则请求是可信的,否则就是不可信的。
API鉴权
先看看阿里云的RAM鉴权
阿里云使用权限来描述用户、用户组、角色对具体资源的访问能力。
权限策略(Policy)
权限策略是用语法结构描述的一组权限的集合,可以精确地描述被授权的资源集、操作集以及授权条件。
通过为RAM用户、用户组或RAM角色绑定权限策略,可以获得权限策略中指定的访问权限。
-
- 效力(Effect):授权效力包括两种:允许(Allow)和拒绝(Deny)。
- 操作(Action):操作是指对具体资源的操作。
- 资源(Resource):资源是指被授权的具体对象。
- 限制条件(Condition): 限制条件是指授权生效的限制条件。
-
策略结构
Example:
- 通过指定的IP地址访问阿里云
{
"Statement": [
{
"Action": "ecs:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {
"IpAddress": {
"acs:SourceIp": "192.168.0.0/16"
}
}
}
],
"Version": "1"
}
- 在指定的时间段访问阿里云。
{
"Statement": [
{
"Action": "ecs:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2019-08-12T17:00:00+08:00"
}
}
}
],
"Version": "1"
}
- 列出并读取一个存储空间中的资源。
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "oss:ListObjects",
"Resource": "acs:oss:*:*:myphotos"
},
{
"Effect": "Allow",
"Action": "oss:GetObject",
"Resource": "acs:oss:*:*:myphotos/*"
}
]
}
RAM鉴权
规则
- 以主账号身份访问
- 以RAM用户身份访问
- 以RAM角色身份访问
主要讲一下RAM角色身份访问
访问令牌
阿里云临时安全令牌(Security Token Service,STS)是阿里云提供的一种临时访问权限管理服务。
接下来是,“阿里云让你模仿,但没有让你超越”
假如我们有一个菜单API如下:
- API1: http://localhost:8001/cargosmart/ssm2014/city/listCitys
- API2: http://localhost:8002/cargosmart/ssm2014/port/createPort
- API3: http://localhost:8003/cargosmart/ssm2014/carrier/deteleCarrier
我需要这个三个接口进行安全访问控制;
1.API保护,可以设计自己的计算签名
2.API鉴权
需要的元素:
-
身份类别
身份类别
2.权限策略结构
阿里云权限策略 demo权限策略结构json格式:
API1: http://localhost:8001/cargosmart/ssm2014/city/listCitys
{
"Statement": [
{
"Action": "ssm2014:listCitys",
"Effect": "Allow",
"Resource": [
"cs:ssm2014:123456:user/UserName",
"cs:ssm2014:123456:group/groupName" ,
"cs:ssm2014:123456:role/roleName"],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2020-04-10T17:00:00+08:00"
}
}
}
],
}
API2: http://localhost:8002/cargosmart/ssm2014/port/createPort
{
"Statement": [
{
"Action": "ssm2014:createPort",
"Effect": "Deny",
"Resource": [
"cs:ssm2014:23456:user/UserName",
"cs:ssm2014:*:group/groupName" ,
"cs:ssm2014:23456:role/roleName"],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2020-04-10T17:00:00+08:00"
}
}
}
],
}
网友评论