亚马逊AWS官方博客

利用亚马逊云科技 IAM Roles Anywhere 授权云外设备访问AWS资源

2022年7月初, 亚马逊云科技推出了IAM Roles Anywhere以允许云外的工作负载(服务器,容器,应用程序和设备等)利用x509证书来获取IAM临时凭证。用户可以使用和云端配置相同的IAM角色和策略来访问AWS资源, 不再需要在云外配置和管理长期凭证,提供和云端一致的使用体验。

在本篇博客中,我们会介绍IAM Roles Anywhere工作原理,以及一些使用场景,最后在设备上配置x509证书完成云端资源访问。

IAM Roles Anywhere 工作原理

首先我们看一下IAM Roles Anywhere 基本概念。

  • Trust anchors:一个Trust anchors代表IAM Roles Anywhere和你的一个CA证书之间的信任关系。设备使用CA颁发的x509证书和trust anchors进行认证以获取临时的IAM凭据。
  • Profiles:用于指定IAM Roles Anywhere可以assume的一些角色,从而获取临时凭据。同时我们也可以在profile里面使用会话策略限制该临时会话的权限。

IAM Roles Anywhere 使用了CreateSession API来提供临时凭据,云外设备通过请求该API,传递trust anchor,profile,assumed role,证书,以及使用证书私钥对该请求生成的SigV4签名等参数。当 IAM Roles Anywhere 收到请求后,它首先使用证书公钥验证签名,然后验证证书是由先前在账户中配置的trust anchor颁发的。 两项验证成功后,应用程序现在已通过身份验证,IAM Roles Anywhere 将通过调用 AWS Security Token Service (AWS STS) 为请求中指定的角色创建新角色会话,以获取临时安全凭证。CreateSession本质上是一个围绕AssumeRole API的x509 wrapper,目前并没有包含在任何的SDK中。详细的认证信息请参考IAM Roles Anywhere 认证。所以在本例中需要使用IAM Roles Anywhere提供的一个credential helper工具, 该工具兼容各种编程语言SDK中的credential_process功能。目前该工具支持Linux,Windows和Darwin这三种平台。

通过为每一个设备分配一个x509证书和私钥,在设备出厂时把证书和私钥封装到操作系统中,设备应用即可以利用IAM Roles Anywhere 服务获取临时密钥以完成亚马逊云科技资源访问。

使用场景

  • IoT 设备访问云端服务,如上传应用日志到亚马逊云科技S3。
  • 机房设备数据备份到S3。
  • 混合云部署中机房的机器访问云端资源。

操作步骤

接下来,我们会一步一步地演示如何利用IAM Roles Anywhere 在设备上上传日志到S3。

前提条件

在使用IAM Roles Anywhere之前确保你已拥有操作IAM Roles Anywhere服务以及IAM role的权限。

Root CA配置

首先,我们需要拥有一个Root CA,如果我们已经有自己的PKI基础设施的话,该步骤可以跳过。这里我们利用亚马逊云科技的Certificate Manager服务来创建一个私有CA证书。具体步骤请参考创建Private CA

这里我们使用了亚马逊云科技的Certificate Manager服务来维护我们的PKI基础设施,当然我们也可以自己去维护一套或者兼容已有的PKI基础设施,如利用OpenSSL或者EasyRSA生成自管理的PKI基础设施。 IAM Roles Anywhere 也支持外部的CA证书。

创建Trust anchors

访问IAM Roles Anywhere控制台,点击Create a trust anchor。这里我选择了Private CA,如果CA是外部CA,选择External certificate bundle导入自己的CA证书。IAM Roles Anywhere是区域性服务,每个区域配置都是独立的,使用时请先切换到对应的区域。

创建 IAM Role

在IAM控制台创建一个角色,可信实体类型为Roles Anywhere。权限为AmazonS3FullAccess,这里角色名字命令为s3-full-access-rolesanywhere, 实际角色权限和名称请根据具体情况修改。

创建 Profiles

进入IAM Roles Anywhere控制台,创建一个profile,这里我们使用上面创建的角色。一个profile可以关联多个角色,但云外设备在使用IAM Roles Anywhere时一次只能选择使用一个角色。另外在profile中可以设置session policy,进而限制角色的权限。Session  policy支持IAM控制台创建的policy也支持针对profile的内联policy。如果配置了session policy,那么设备可以获取的权限即是角色和session policy权限的交集。

此时我们已经完成了Trust anchors和Profile的创建。

生成设备证书

进入亚马逊云科技Certificate Manager控制台,为设备请求一个私有证书

在对证书设定FQDN的时候,如果是一批设备使用同一个证书的话,可以设置前缀为设备型号,如果是每个设备一个单独的证书,可以设置前缀为设备的uuid,以便区分和后续管理维护。

请求完证书后,点击证书ID,选择导出。默认导出的证书私钥需要被加密,这里使用如下命令解密私钥文件。device-pass.key是加密的私钥文件,device.key是解密后的私钥文件。

openssl rsa -in device-pass.key -out device.key

配置设备凭据并测试应用程序

本例以设备为linux系统为例,首先进入用户家目录,然后下载credential helper 工具,验证该可执行程序并赋予可执行权限。

安装CLI并配置凭据

配置aws_signing_helper程序作为credential process来获取认证凭据,为设备启用无人值守访问。

File: .aws/config

[default]
region = us-east-1
credential_process = /home/mile/.aws/aws_signing_helper credential-process \
--certificate /app/device.crt --private-key /app/device.key \
--trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID \
--profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID \
--role-arn arn:aws:iam::account:role/role-name-with-path 

我们将设备证书和应用程序放在 /app 路径下,下面为详细信息:

File:  s3upload.py

#!/usr/bin/env python3
import logging
import boto3
from botocore.exceptions import ClientError
import os
import argparse

parser = argparse.ArgumentParser(description='Upload a file to an S3 bucket.')
parser.add_argument('-f', '--file', required=True, help='File to upload')
parser.add_argument('--bucket', required=True, help='Bucket to upload to')
parser.add_argument('--object', help='S3 object name. If not specified then file_name is used')

args = parser.parse_args()


def upload_file(file_name, bucket, object_name=None):
    """Upload a file to an S3 bucket

    :param file_name: File to upload
    :param bucket: Bucket to upload to
    :param object_name: S3 object name. If not specified then file_name is used
    :return: True if file was uploaded, else False
    """

    # If S3 object_name was not specified, use file_name
    if object_name is None:
        object_name = os.path.basename(file_name)

    # Upload the file
    session = boto3.Session()
    s3_client = session.client('s3')
    try:
        response = s3_client.upload_file(file_name, bucket, object_name)
    except ClientError as e:
        logging.error(e)
        return False
    return True

upload_file(args.file, args.bucket, args.object)

现在我们已经完成了设备所有的配置,可以执行测试程序了。

Command

./s3upload.py -f hello.txt --bucket bucket_name

从S3控制台可以看到hello.txt文件已经上传成功了。

身份限制和安全管理

证书和IAM Roles Anywhere的身份映射

设备可以使用证书来获取临时凭据,X509 证书中的 Subject 和 Issuer 字段被提取并用作会话中的 PrincipalTag 元素。另外IAM Roles Anywhere 也会将 SourceIdentity 值设置为Subject的 CN,所以如果只想对CN做限制,可以直接用SourceIdentity作为condition。例如,上述我们的设备证书Subject中的CN字段是device2022.mile.org,那么在设备的会话中,该信息就会被添加到session中作为PrincipalTag: aws:PrincipalTag/x509Subject/CN,这样我们就可以对刚才创建的IAM角色使用基于ABAC的条件信任策略。针对上面创建的角色s3-full-access-rolesanywhere,设置信任策略如下所示:

因为我们的证书CN为device2022与图中策略设置device2021不同,所以此时设备再去访问s3就会出现拒绝访问,如下图所示:

除了利用Subject中的CN进行额外限制外, 还支持证书Subject中的其他身份信息字段,如O,OU等。因此我们可以设定基于标签的访问策略以限制特定组织部门下的特定设备或某一批设备权限,如下所示:

IAM Roles Anywhere CRL 配置

在实际生产环境中,我们可能会希望能够主动去撤销这些证书的权限,如以下情况:

  • 设备被入侵,导致私钥泄露。
  • CA 私钥泄露。
  • 旧证书需要被新的证书替换。
  • 设备需要被淘汰。

遇到这些情况下我们可以对之前颁发的证书进行吊销,然后在IAM Roles Anywhere中导入CRL文件,并启用CRL配置,这样被吊销的证书在获取凭据时就会被直接拒绝。目前CRL配置只能通过CLI进行操作,具体操作如下:

  1. 使用如下命令更新之前创建的Private CA的CRL配置,将该Private CA的CRL文件存储到S3上,桶策略配置请参考 CRL S3 访问策略

File: revoke_config.txt

{
   "CrlConfiguration":{
      "Enabled":true,
      "ExpirationInDays":7,
      "S3BucketName":"DOC-EXAMPLE-BUCKET",
      "S3ObjectAcl":"BUCKET_OWNER_FULL_CONTROL"
   }
}

Command

aws acm-pca update-certificate-authority \
	--certificate-authority-arn "arn:aws:acm-pca:region:account:certificate-authority/CA_ID" \
	--revocation-configuration file://revoke_config.txt

执行完上述命令,等待一会后,在我们配置的S3桶上crl前缀下已经生成了CA_ID.crl文件。

  1. 对颁发的证书进行吊销,吊销证书后稍等一会,S3上crl文件更新通常需要30分钟左右,快的话在几分钟内就可以了,通过对比crl文件大小或者修改时间即可确认该文件是否已被更新。
aws acm-pca revoke-certificate \
--certificate-authority-arn arn:aws:acm-pca:region:account:certificate-authority/12345678-1234-1234-1234-123456789012 \ 
--certificate-serial 67:07:44:76:83:a9:b7:f4:05:56:27:ff:d5:5c:eb:cc \ 
--revocation-reason "KEY_COMPROMISE"
  1. 下载一开始在S3上配置的CRL文件,导入CRL到IAM Roles Anywhere。
openssl crl -text -inform DER -in 12345678-1234-1234-1234-123456789012.crl > device2022.pem

aws rolesanywhere import-crl --crl-data fileb://device2022.pem \
--name device2022 \
--trust-anchor-arn arn:aws:rolesanywhere:us-east-1:123456789012:trust-anchor/12345678-1234-1234-1234-123456789012 

执行完上述命令后,即可返回crl的json详细信息,这里我们可以看到enabled是false,复制crlid的值。

  1. 启用CRL配置。
aws rolesanywhere enable-crl --crl-id 12345678-1234-1234-1234-123456789012

此时在输出结果中可以看到enabled是true,表明crl已经启用。

  1. 验证设备证书凭据已失效。

执行命令,显示证书已经被吊销了,无法访问云上资源了。

拓展延伸

在本例中我们直接使用了根证书对终端设备进行证书颁发。在实际的大型生产环境中,我们需要设计CA的层次结构,根CA签署从属于自身的其他CA证书,这些CA证书也称中间CA证书,以便更好地划分管理任务和完成精细安全控制等。如利用根CA证书针对各个业务部门颁发各自的中间CA证书,由各个业务部门去管理和控制自己旗下的设备证书。下图说明了简单的三级CA层次结构。

总结

在本篇博客中,我们介绍了IAM Roles Anywhere 工作原理,使用案例和配置步骤,以及如何对IAM Roles Anywhere进行权限控制和快速吊销设备会话凭据,最后我们介绍了一些关于设备证书的延伸信息。

本篇作者

张春明

亚马逊云科技解决方案架构师,对于操作系统,网络,数据库,安全都有深入的了解。他帮助客户设计云上解决方案,并致力于解决客户使用过程中遇到的各种疑难杂症,加速客户云上业务构建。在业余时间,他喜欢学习新技术、听歌、阅读小说、骑行和滑雪等。他信奉的人生格言是人生苦短,何妨一试。