Tag: AWS IAM


从永恒之蓝开始,安全防范没有结束

信息安全现状

时钟进入到2017年,物联网安全DDoS攻击勒索软件被越来越多的国内外信息安全预测机构列为年度最大信息安全威胁。上周爆发的勒索软件WannaCry (又称作永恒之蓝)已席卷全球99个国家,让各类技术宅男们和信息安全的童鞋们又错过了一个美好的周末。尽管目前该病毒已被安全人员找到了阻止其传播的方法,但是类似的安全事件依然给我们敲响了云端安全运维的警钟。

WannaCry事件回顾,5月12日晚, WannaCry 蠕虫病毒在全球大肆爆发。据外媒报道,攻击在99个国家实施了超过75000次攻击。该攻击利用漏洞MS17-010中的某些版本的SMB服务器协议进行传播,利用Windows 445 端口的安全漏洞潜入电脑并对多种文件类型加密并使用户无法打开,攻击者称需支付比特币解锁,补丁程序已于2017年3月14日发布,但未打补丁的用户有可能遭受此次攻击。通过这个事件我们发现只要是购买正版操作系统并及时更新补丁的用户,都不会受到影响。永久解决办法有2个,1.开启windows的自动更新功能,将最新补丁打上; 2.对于部分比较老的windows系统可以手动下载更新包并安装。

这样的安全事件不是第一次也不会是最后一次,要确保我们的信息安全,需要做的事情有太多,比如完善的信息安全应对机制,一系列自动化运维工具或服务,坚决的执行能力以及定期的审核机制。如果你恰好开始关心信息安全,而我们又专业,不妨看看AWS是如何看待信息安全的。

AWS信息安全理念

数据属于谁?

虽然是一个老生常谈的问题,但确实一个非常重要的问题,而且答案永远只有一个,数据属于客户。当你上云之后,如何确保你的数据真的属于你是很多客户评估是否上云时最纠结的问题!在AWS,你可以非常清晰的从上图中看到这个界限。所有操作系统以上(包括操作系统本身)的内容都是客户自己自主可控,AWS没有任何权限访问,同时如果你使用的是AWS提供的Windows或者Linux镜像,该镜像 的补丁机制是全球一致管理的,我们会从各个合作厂商那得到补丁,并第一时间更新到镜像里。如果是开篇提到的流氓攻击,在AWS上的客户可以不需要担心了,因为该补丁在镜像中自动更新了。

如何确保我在云上是安全的?

如何数据安全可能是一个说上三天三夜都没法说完的话题,今天我们从AWS信息安全最佳实践出发,给大家从几个层面来分析信息安全的层级,并重点介绍如何帮助客户在理解理念之后的安全落地问题。首先我们可以看到在云上我们需要这么几个维度的安全,底层基础架构的安全网络的安全权限及审计的安全服务本身的安全事先预防等等。总之,信息安全从来都不是靠说的,而是靠做的,所以接下来我们给大家做一些简单示范,让你在使用AWS时更加得心应手。

底层基础架构的安全

熟悉AWS的同学可能知道,AWS底层的虚拟化平台使用的是Xen,套用一句官话,不管我们的工程师是多么的小心,我们依然需要时刻告知我们的客户对于AWS服务底层安全的疑虑,所以大家可以在以下链接找到关于Xen的信息安全公告,同时大家也可以从AWS信息安全白皮书中看到AWS如何对于底层基础架构的安全设计,限于篇幅的原因本文不作展开。

Xen Security Advisiories

https://aws.amazon.com/cn/security/security-bulletins/

AWS Security Best Practices

https://d0.awsstatic.com/whitepapers/aws-security-whitepaper.pdf

网络安全

  • 上云的安全

当你的数据需要上云时,你有三种非常安全的方式来传输您的数据,通过TLS加密的HTTPS协议将数据直接通过互联网传输到S3, 建立专用VPN进行数据传输以及通过专线将AWS与您的数据中心打通,并将AWS纳入您现有的全球专线网络中,让你全球任何一个办公室或者数据中心都通过内网的方式随时的安全访问云端的数据或者系统,如同您多了一个拥有无限扩展能力的远端数据中心。

  • 云上的安全

当您的数据或者系统已经部署在AWS上时,你可以通过上图的简单示意图来对您的系统进行网络隔离及控制。比如,你可以按照不同的应用划分不同的VPC,不同的VPC之间网络隔离,同时在同一个VPC内设置不同安全级别网络区域,如公有访问区,DMZ区,私有网络区。利用VPC内的免费防火墙工具安全组,网络ACL来对云端的机器及网段进行精细化控制。如图上的例子,你可以通过图形界面在安全组上关闭该机器137,139,445 端口就能轻松的规避本文开篇提到的流氓攻击。如果您确实需要开启这些端口,也可以在安全组内指定对具体的源IP开放端口,或者将这些机器放置在私有网段,当这些私有网段的机器需要访问互联网的某些站点进行补丁升级等操作时,通过NAT的方式允许VPC的出向流量。

如果您还需要对VPC内不同私有网段的机器访问进行更精细化控制,还可以通过另外一个免费的防火墙网络ACL来实现。

当您的网络与AWS云端VPC通过VPN或者专线联通时,你还可以通过路由表来控制您哪些数据中心的网段可以访问云端的哪些网段。

权限及审计安全
当你的业务上云后,你可能面临不同人员需要管理你云端资源,这些人可能包括,您公司的开发人员,运维人员,财务部,人事部以及您外部形形色色的服务供应商或者运维外包供应商,如何给予这些人员适当权限去访问他们需要访问的AWS资源以及事后审核这些人员的访问情况,是很多企业客户迫切需要解决问题。

AWS IAM不但可以轻松解决上述所有访问权限问题,还可以帮您打通绝大部分企业遇到的SSO问题,让你数据中心的AD或者第三方机构与AWS建立授权机制,当您的用户在本地AD通过验证后,直接访问AWS上的数据,无需重复创建用户。同时可以给所有IAM用户开启复杂密码功能,并强制用户每隔一段时间修改密码。

内审或者外审通常是一个企业每年必做的事情,在AWS只需开启CloudTrail服务就可以自动记录所有AWS资源的使用情况,下图是一个CloudTrail的简单示例,我们可以看到什么时间哪个用户对什么资源做了什么事情。

同时还可以进一步查看某个事件的详细信息,便于审核,如下图所示:

服务本身的安全机制

由于AWS服务众多,限于篇幅的原因,本文重点讲解AWS虚拟机(EC2)的安全,如您对其他服务也很感兴趣,欢迎阅读AWS安全白皮书。

AWS Security Best Practices

https://d0.awsstatic.com/whitepapers/aws-security-whitepaper.pdf

     Amazon EC2多层安全模型

Amazon EC2多层安全模型包含底层物理服务器的操作系统,虚拟操作系统或者客户操作系统,防火墙和签名的API调用。目标是防止EC2内的数据被未授权的系统或者用户访问,在不牺牲客户配置灵活性的时,尽最大限度保证EC2本身的安全。

Amazon EC2当前利用了一个AWS高度定制化的Xen hpervisor,底层托管主机操作系统执行Ring0(最高权限),客户操作系统执行Ring1,应用执行Ring3(最低权限)在虚拟化层面来隔离客户和hypervisor。

当多台EC2运行在同一台底层物理服务器时,他们被Xen hypervisor隔离,如上图所示,在hypervisor层中有防火墙,且该防火墙位于底层物理网卡和客户EC2虚拟网卡之间。所有流量都需要通过该层,所以任意一个EC2实例无法访问其他EC2实例,底层的内存(RAM)也是使用类似机制实现隔离。

底层硬件的操作系统都必须通过MFA的方式进行访问,且这个系统通过AWS
特殊设计,构建及配置,确保其安全,所有访问都会自动记录且被审计。

客户操作系统完全有客户控制,客户拥有完整的根或者管理员权限,AWS没有任何权限可以访问。

重要数据经常备份,重要数据经常备份,重要数据经常备份,重要的事情说三遍。 在AWS你可以将常用对象数据存放在EBS或者S3,对于存放在EBS的数据每天EBS快照,确保任何重要数据都有一份最近的拷贝。对于S3上的对象数据,通过S3 桶策略进行精细控制,同时开始S3的版本控制功能防止误删或脏数据。

事先预防

如何做好事先预防工作呢?比如某用户处于某种原因开启了一些高端口或者公司命令禁止的网络端口,IT部门如何迅速发现并纠正呢?AWS Config服务可以帮到你。Config可为您提供 AWS 资源的详细库存及其当前配置,并会持续记录对这些资源配置所做的更改(例如,安全组的出/入规则、适用于 VPC 的网络 ACL 规则和 Amazon EC2 实例上标签的值)。

您可以通过创建 AWS Config 规则进行评估,规则规定了您理想的配置设置。AWS Config 能够提供可自定义的预定义规则 (称作托管规则),以帮助您开始进行评估。您还可以创建自己的自定义规则。在 AWS Config 持续跟踪您的资源中出现的配置更改时,它会检查这些更改是否违反了规则中的任何条件。如果某个资源违反了规则,那么 AWS Config 会将该资源和规则标记为不合规。例如,当创建 EC2 卷时,AWS Config 可以按照需要卷加密的规则来评估该卷。如果卷没有加密,AWS Config 会将卷和规则标记为不合规。AWS Config 还可以在您的所有资源中检查有无账户范围内的要求。例如,AWS Config 可以检查账户中 EC2 卷的数量是否在所需总数以内,或者账户是否使用 AWS CloudTrail 进行登录。

如何进行远程系统管理

Amazon EC2 系统管理器是一系列可帮助您自动执行管理任务的功能,例如收集系统清单、应用操作系统补丁、自动创建 Amazon 系统映像 (AMI) 以及大规模配置操作系统和应用程序。您可以使用 Systems Manager 以远程方式安全地管理托管实例的配置。托管实例是您混合环境中已经针对 Systems Manager 配置的任意 Amazon EC2 实例或本地计算机。系统管理器所提供的功能和共享组件无需额外费用。您仅需为实际使用的 Amazon EC2 资源付费。

 

系统管理器支持对下列操作系统进行管理:

Windows操作系统 Windows Server 2003 至 Windows Server 2016,包括 R2 版本
Linux操作系统

64 位和 32 位系统

Amazon Linux 2014.09、2014.03 或更高版本

Ubuntu Server 16.0.4 LTS、14.04 LTS 或 12.04 LTS

Red Hat Enterprise Linux (RHEL) 6.5 或更高版本

CentOS 6.3 或更高版本

仅 64 位系统

Amazon Linux 2015.09、2015.03 或更高版本

Red Hat Enterprise Linux (RHEL) 7.x 或更高版本

CentOS 7.1 或更高版本

如果大家感兴趣,可以参考下面链接进行具体的配置安装。

http://docs.amazonaws.cn/systems-manager/latest/userguide/what-is-systems-manager.html

接下来介绍使用系统管理器来进行补丁安装。由于北京区的系统管理器暂无补丁管理组件,我们使用Run Command组件来进行补丁安装。您可以使用系统管理器的Run Command以远程方式安全地管理托管实例的配置。托管实例是您混合环境中已经针对系统管理器配置的任意 Amazon EC2 实例或本地计算机。利用 Run Command,您可以自动完成常用管理任务以及大规模执行临时配置更改。

管理员使用 Run Command 可以在其托管实例上执行以下类型的任务:安装或引导应用程序,安装系统补丁,获取系统资产信息,构建部署管道,从 Auto Scaling 组终止实例时捕获日志文件,以及将实例加入 Windows 域等等。

写在最后的话

一波热闹的攻击事件已经过去,下一次攻击开始还会远吗?如果您能事先利用AWS提供的信息安全服务(文中提到的很多服务是免费的),配合完善的审核机制,不管是什么类型的信息安全风险来临你都能处乱不惊。

 

使用AWS控制台或命令行将AWS IAM角色附加到现有的Amazon EC2实例中

简介

AWS IAM(身份和访问管理服务)中的角色使您的应用程序在Amazon EC2上能够使用临时的安全凭证自动实现AWS服务的创建,发布和内容修改。使用这样的临时凭证是IAM的最佳做法,因为您不再需要在实例上维护一个或多个长期密钥。对EC2使用IAM角色也无需再使用必须手动或以编程方式管理的长期AWS访问密钥。

例如,应用程序必须通过AWS证书签署API请求。因此,如果您是应用程序开发人员,您需要一个策略来为EC2实例上运行的应用程序管理证书。您可以安全地将您的AWS证书分配至实例,从而允许这些实例上运行的应用程序使用您的证书签署请求,并保护其免受其他用户的影响。但是,要将凭证安全地分配至每项实例有一定难度,尤其是AWS以您的名义创建的实例,例如竞价型实例或Auto Scaling组中的实例。当您更换AWS证书时,您还必须能够更新每项实例上的证书。IAM角色能够委托授权以发出API请求,而不用创建并分配您的AWS证书。详细解决方案,请查阅文档适用于Amazon EC2的IAM角色

之前,IAM角色只能在实例创建设置时添加,这导致了过去创建的实例和忘记添加IAM角色的实例无法使用IAM角色操作实例,从而被迫重新部署实例及应用程序。从现在开始,您可以通过将IAM角色附加到现有的尚未被角色附加的EC2实例,来使用AWS提供的临时安全证书操作EC2实例,您还可以随时替换附加到现有EC2实例的IAM角色。

适用范围

文中的操作步骤已于2017年2月23日验证通过,其中AWS CLI版本1.11.48,在AWS全球和AWS中国区均能正常使用。

解决方案

1.   创建IAM角色

2.   将IAM角色附加给现有EC2实例(最初没有IAM角色附加)

3.   更换附加到Amazon EC2的IAM角色

4.   移除附加到Amazon EC2的IAM角色

本文假设您具有创建IAM角色的权限,并具有调用EC2 API的权限。

AWS命令行操作步骤中所有出现的占位符{Some Words},都应该替换为实际资源名称。

AWS控制台操作步骤

1.  打开EC2控制面板,并选择左侧边栏的“实例”。

2.  选择您的实例,依次点击上方的操作->实例设置->Attach/Replace IAM role

3.  打开IAM role下拉菜单,选择您想要附加给当前EC2的IAM角色,No Role代表不附加角色,选好后点击右侧的Apply按钮。选择并应用的过程实际上包含了:将IAM角色附加给现有EC2实例(最初没有IAM角色附加);更换附加到Amazon EC2的IAM角色;移除附加到Amazon EC2的IAM角色。

4.  如果您选择了No Rule(即移除EC2上的IAM角色),会显示如下页面:

5.  如果您未作出有效的修改,会显示如下页面:

6.  如果您的修改有效,会显示如下页面:

AWS命令行操作步骤

开始操作之前,请确保您的CLI版本大于等于1.11.48。如果您对当前自己的CLI版本有疑问,可以在命令行中执行以下命令进行版本查询:

$aws --version

如果您已经有 pip 和支持的 Python 版本,则可以使用以下命令安装 AWS CLI:

# pip install --upgrade --user awscli

一、创建IAM角色

在从AWS CLI创建IAM角色之前,必须先创建角色信任策略。信任策略允许AWS服务(如EC2)代表您的应用程序承担IAM角色。

要创建信任策略,请复制以下策略,并将其粘贴到使用名称{YourNewRole}-Trust-Policy.json保存的文本文件中,注意后缀名为.json:

♦AWS中国区

{

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

"Statement": [

{

"Effect": "Allow",

"Principal": {

"Service": "ec2.amazonaws.com.cn"

},

"Action": "sts:AssumeRole"

}

]

}

♦AWS全球

{

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

"Statement": [

{

"Effect": "Allow",

"Principal": {

"Service": "ec2.amazonaws.com"

},

"Action": "sts:AssumeRole"

}

]

}

 

现在您已成功创建信任策略,接下来创建IAM角色{YourNewRole}:

1.  基于信任策略创建IAM角色{ourNewRole},打开命令行并执行以下命令:

$aws iam create-role --role-name {YourNewRole} --assume-role–policy-document file://{FilePath}/{YourNewRole}-Trust-Policy.json

注意:  file:// 不能省略,策略路径可以是当前相对路径也可以是全路径。

例如:

相对路径: file://TestRole-Trust-Policy.json

全路径:

Windows:file://C:/test/TestRole-Trust-Policy.json

Linux: file:///data/test/TestRole-Trust-Policy.json

2.  给予此IAM角色访问帐户中资源的权限。在本示例中,我假设您的应用程序需要只读访问您帐户中的所有Amazon S3存储桶和存储桶中的对象。因此,您将使用AmazonS3ReadOnlyAccess AWS托管策略。有关AWS托管策略的详细信息,请参阅使用托管策略。在命令行中执行以下命令:

$aws iam attach-role-policy --role-name {YourNewRole} --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

3.  创建IAM实例配置文件{YourNewRole-Instance-Profile}。实例配置文件允许EC2将IAM角色{YourNewRole}传递给EC2实例。要了解更多信息,请参阅使用实例配置文件。在命令行中执行以下命令:

  $aws iam create-instance-profile --instance-profile-name {YourNewRole-Instance-Profile}

  $aws iam add-role-to-instance-profile --role-name {YourNewRole} --instance-profile-name {YourNewRole-Instance-Profile}

至此,您已成功创建IAM角色{YourNewRole}。

 

二、将IAM角色附加给现有EC2实例(最初没有IAM角色附加)

您现在可以将IAM角色{YourNewRole}附加到EC2实例{YourInstanceId}:

1.  获取现有EC2实例详细信息(记录InstanceId)。在命令行中执行以下命令:

$aws ec2 describe-instances

2.  将新创建的IAM角色{YourNewRole}的实例配置文件{YourNewRole-Instance-Profile} 附加到您的EC2实例{YourInstanceId}。在命令行中执行以下命令:

$aws ec2 associate-iam-instance-profile --instance-id {YourInstanceId} --iam-instance-profile Name={YourNewRole-Instance-Profile}

3.  验证IAM角色是否已附加到实例。在命令行中执行以下命令:

$aws ec2 describe-iam-instance-profile-associations

4.  打开AWS EC2控制台,查看实例的描述信息:

5.  进入EC2实例内,查看实例IAM角色具体信息:

$curl http://169.254.169.254/latest/meta-data/iam/security-credentials/{YourNewRole}

至此,您可以使用IAM角色访问AWS资源来更新应用程序,并把实例中的长期密钥删除。

三、更换附加到Amazon EC2的IAM角色

如果角色的使用需求发生改变,并且您希望通过修改IAM角色来授予EC2实例权限,则可以更换换附加到EC2的IAM角色。但是,这也将修改使用此IAM角色的其他EC2实例的权限。

可以采用调用replace-iam-instance-profile-association调用替换IAM角色命令, 将当前附加的IAM角色{YourNewRole}更换为另一个IAM角色{YourReplacementRole}(例如:EC2role2),而不终止您的EC2实例:

步骤:

1.  创建新的IAM实例配置文件{YourReplacementRole-Instance-Profile}指向新的IAM角色{YourReplacementRole},例如EC2Role。创建命令参考上节内容。

2.  获取现有EC2实例IAM附加信息(记录AssociationId)。在命令行中执行以下命令:

$aws ec2 describe-iam-instance-profile-associations

使用过滤条件和控制查询输出内容,获取指定EC2实例的

$aws ec2 describe-iam-instance-profile-associations --filters Name=instance-id,Values=i-79dxxxx --query

    'IamInstanceProfileAssociations[*].{InstanceId:InstanceId,AssociationId:AssociationId}' --output table

3.  更换IAM角色。在命令行中执行以下命令:

$aws ec2 replace-iam-instance-profile-association --association-id {YourCurrentAssociationId}

    --iam-instance-profile Name={YourReplacementRole-Instance-Profile}

4.  根据AssociationId的值看出,IAM角色的更改已生效。打开AWS EC2控制台,查看实例的描述信息:

四、移除附加到Amazon EC2的IAM角色

在实际使用过程中,您的EC2可能不再需要通过角色使用AWS资源。这时候您可以选择移除附加在EC2上的IAM角色。

可以采用调用disassociate-iam-instance-profile调用移除IAM角色命令:

步骤:

1.  获取现有EC2实例IAM附加信息(记录AssociationId)。获取IAM信息命令参考上一节所述

2.  移除IAM角色。在命令行中执行以下命令:

$aws ec2 disassociate-iam-instance-profile --association-id {YourCurrentAssociationId }

3.  根据第二次查询现有EC2实例IAM附加信息为空可以看出,当前实例的IAM角色已被移除。

而在上述所有操作的过程中,均未影响EC2的运行状态。

总结:

做为安全最佳实践,让我们现在就行动起来,将所有需要使用AWS资源的Amazon EC2上添加对应的角色。

参考

[1]New! Attach an AWS IAM Role to an Existing Amazon EC2 Instance by Using the AWS CLI

[2]AWS命令行参考手册

[3]Demo脚本下载

 

作者介绍:

王元恺

AWS实习解决方案架构师,上海交通大学学生,有数年C++程序开发以及一年PHP前后端开发经验,同时致力于AWS云服务在国内的应用和推广。熟悉网站架设与网络应用开发,对于TCP/IP及网络协议有自己的理解和实践经验。

陈琳涛

AWS解决方案架构师。拥有超过15年的IT行业以及软件开发领域的工作经验。2000年投身互联网大潮,创办过自己的公司。长期从事网络相关研发和管理工作,热爱DevOps实践。随后,投身游戏行业,参与多个项目的研发,运维,上线工作。致力于使用云计算来帮助更多的创业者迈向成功。

Token Vending Machine:移动应用客户端安全访问AWS服务的解决方案

背景介绍

广大移动互联网应用和移动游戏开发者在利用AWS服务进行开发过程中,经常需要为移动客户端提供AWS服务访问安全证书,以便让这类移动端应用有权限直接访问AWS服务,比如通过AWS S3服务上传图片文件或者通过AWS SQS服务发送消息。

有些移动开发者可能会考虑为每个移动应用用户分配一个固定的AWS IAM安全证书来实现移动客户端访问AWS服务。但是一款热门的移动互联网应用或者移动游戏往往拥有数百万甚至上千万的用户基数,让系统管理员为每一个用户分配和管理IAM 安全证书工作量将会非常巨大。而且移动客户端相对服务器端具有较低的安全等级,保存在移动设备内部的敏感信息比如用户账号或密码存在泄露的风险,强烈建议移动开发者不要将AWS安全证书长期保存在用户的移动设备中。

利用AWS 安全令牌服务Security Token Service (简称STS)可以动态的为大量移动客户端用户分配临时安全证书 ,并且可以限制这些临时安全证书的AWS服务访问权限和有效时间。使用AWS STS临时安全证书没有用户总数的限制,也不需要主动轮换,证书自动会过期,拥有非常高的安全性。对于这种采用AWS STS和其他相关AWS服务构建的移动客户端访问AWS服务安全证书分配系统,我们把它命名为Token Vending Machine,即令牌售卖机,简称TVM。

下面我们以一个典型的手机图片管理APP演示项目为例来介绍如何利用AWS相关服务设计和开发一套TVM系统。读者可以通过参考演示项目的设计思想和相关源码快速开发出符合自己项目需求的TVM系统。

假设该演示项目的基本需求如下:

1) 用户在使用该APP前要先完成注册

2)   用户成功登录后可以通过APP上传,查看和管理自己的图片

3)   用户不可以访问到其他用户的图片

实现原理


整个演示项目实现可以分为三个主要模块:移动客户端、TVM系统和S3服务。

A. 移动客户端

  • 包括访问TVM系统获取临时安全证书的客户端代码
  • 包括直接访问AWS S3存储桶用户个人目录内容和图片管理相关的代码逻辑实现。

B. TVM系统

  • 使用了一台AWS EC2实例来运行Apache Tomcat Web服务器,用于向移动客户端提供远程访问接口以获取临时安全证书。在Tomcat内部则部署了使用JAVA语言开发的TVM服务器端实现。
  • 使用了AWS 高性能的NoSQL数据库DynamoDB做为后台用户数据库。该数据库用来保存注册用户的账号、密码和会话Key等信息。

开发者自行设计和实现TVM系统的时候,完全可以使用自己熟悉的数据库产品或者集成第三方已有的用户数据库服务,比如基于LDAP的企业内部用户数据库。

  • TVM系统的JAVA实现通过访问AWS STS服务获取临时安全证书以提供给移动客户端。
  • 在真实的项目中,运行TVM系统的服务器端往往还将直接管理S3中保存的所有用户资源,比如可以限制每个用户允许上传图片的数量和文件合计大小等等。这部分功能在本演示项目中暂时没有实现。

C. S3服务

  • AWS S3服务为用户上传图片提供了持久化存储能力。

在用户成功完成账号注册后,TVM系统的基本工作流程如下:

1) 用户通过移动客户端输入账号和密码,登录系统。

2) TVM查询用户数据库,校验账号和密码组合的合法性。

3) TVM访问AWS STS服务,请求分配临时证书,TVM将获得的临时安全证书返回移动客户端。

4) 移动客户端使用获取的临时安全证书,调用AWS S3 API,执行文件的上传、列表和下载等操作。

部署过程

  1. 使用IAM用户账号登录AWS控制台
  2. 创建IAM EC2角色
  3. 创建临时安全证书角色
  4. 在Launch TVM EC2实例的过程中,选择使用创建的IAM EC2角色
  5. 在TVM EC2实例中部署Tomcat和TVM war包
  6. 下载并安装TVM apk文件到安卓移动终端

细节说明

IAM EC2角色定义

基于对生产环境高安全性要求的考虑,我们没有在JAVA代码中直接使用静态配置的IAM用户Access Key Id和Access Key来访问AWS DynamoDB, S3和STS等AWS服务,而是希望使用AWS动态分配的临时安全证书。为此我们创建了一个专门的IAM EC2角色,并为该角色赋予了足够的AWS服务访问权限。这样一来,运行在带有该IAM角色的EC2实例中的TVM组件,就可以通过EC2上下文获得拥有足够AWS服务访问权限的临时安全证书。请注意不要将TVM组件自己使用的临时安全证书与TVM组件将为移动客户端分配的临时安全证书相混淆。这里通过EC2上下文获取的临时安全证书主要用于TVM组件在服务器端访问AWS相关服务,比如读写DynamoDB或者向STS服务请求为移动客户端分配临时安全证书。

下面的例子IAM Policy文件赋予了IAM EC2角色访问AWS STS服务的AssumeRole接口和其他AWS服务的权限。开发者可以根据自己的实际需求增加或减少相关权限分配。

{

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

    "Statement": [

        {

            "Effect": "Allow",

            "Action": "sts:AssumeRole",

            "Resource": "*"

        },

        {

            "Effect": "Allow",

            "Action": [

                "sqs:*" ,

                "sns:*" ,

                "dynamodb:*"

            ],

            "Resource": "*"

        },

        {

            "Effect": "Allow",

            "Action": [

                "s3:*"

            ],

            "Resource": "*"

        }

    ]

}

TVM组件实现代码在构造STS服务访问客户端对象的时候,我们使用了AWS JAVA SDK提供的com.amazonaws.auth.InstanceProfileCredentialsProvider证书加载类文件。该类实例可以自动访问EC2运行环境上下文,获取临时安全证书以供构造的STS服务访问客户端对象使用。并且当获取的临时安全证书即将失效时,该类实例还可以自动去获取新的安全证书。通过使用该类实例,TVM组件开发者就不再需要考虑访问STS或DynamoDB服务时需要提供的安全证书问题。

下面的代码片段演示了如何构建一个带有自动安全证书管理能力的STS服务访问客户端对象。

代码片段来自于TVM组件的com.amazonaws.tvm.TemporaryCredentialManagement.java源文件。

AWSSecurityTokenServiceClient sts =

    new AWSSecurityTokenServiceClient(

        new InstanceProfileCredentialsProvider() );         

STS API方法选择和使用

AWS STS服务提供了多个API方法,分别用于不同场景下的临时证书获取。其中的AssumeRole 方法是唯一支持临时安全证书调用的。这种STS API方法的调用方式看上去非常有趣:我们使用了来自EC2上下文的临时安全证书去调用STS AssumeRole 方法,目的是为了帮助移动客户端用户申请访问AWS S3服务的临时安全证书。实际上通过EC2上下文获取的临时安全证书也是来自AWS STS服务的动态分配。这一点恰恰也证明了AWS服务的松耦合设计思想,用户可以通过灵活组合不同的服务来达到自己的设计目的。


STS AssumeRole 方法提供了多个参数,可以灵活的设置分配的临时安全证书的各种特性。我们这里主要介绍演示项目用到的几个重要参数。

 
名称 类型 必填 含义
DurationSeconds 整型

以秒为单位的临时安全证书有效时间限制。最小可以是15分钟(900秒),最大可以是1个小时(3600秒)

默认值:3600秒。

RoleArn 字符串

临时安全证书对应的角色Arn值。开发者在为移动客户端分配临时安全证书的时候,需要首先在AWS系统中创建该角色对象,并且为角色设置适当的权限。STS AssumeRole方法返回的临时安全证书的权限就将以该角色所拥有的权限为基础。如果开发者调用STS API时候还提供了Policy参数,返回的安全证书权限还将在此基础上做进一步限制。以两个参数提供权限的交集作为返回的临时安全证书的最终权限设置。

RoleArn格式举例:

“arn:aws-cn:iam::358620XXXXXX:role/TVMClientRole”

Policy 字符串 以Json格式表示的附加权限设置。如果该参数被设置,STS服务将使用RoleArn参数中指定的角色对应的权限和该参数设置权限的交集来定义即将返回的安全证书的权限。一种常用的做法就是使用该参数来进一步限制返回安全证书的权限到每个具体的实体。在我们的演示项目中,就是通过设置Policy来进一步限制每个登录用户只能访问属于自己的S3文件。
RoleSessionName 字符串

角色会话名称,主要用来区分申请临时安全证书的不同用户或者不同使用场景。

在我们的演示项目中,设置的角色会话名称就是用户通过手机客户端应用输入的登录名。

下面的代码片段演示了如何调用STS AssumeRole方法申请新的临时安全证书。

代码片段来自于TVM组件的com.amazonaws.tvm.TemporaryCredentialManagement.java源文件。

//构造请求对象

AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest();

 

assumeRoleRequest.setRoleArn("Arn of your TVM role");

 

assumeRoleRequest.setPolicy(

        TemporaryCredentialManagement.getPolicyObject( myUserName ));

 

assumeRoleRequest.setRoleSessionName(myUserName);

 

assumeRoleRequest.setDurationSeconds(

new Integer( Configuration.SESSION_DURATION ));   

 

//获取临时安全证书

AssumeRoleResult assumeRoleResult = sts.assumeRole(assumeRoleRequest);

 

if (assumeRoleResult != null && assumeRoleResult.getCredentials() != null)

{   

    log.info("利用EC2角色从STS服务获取临时证书操作成功!");

 

    log.info("AccessKeyId = "

    + assumeRoleResult.getCredentials().getAccessKeyId());

 

}

else

{

    log.warning("利用EC2角色从STS服务获取临时证书操作失败!");

}       

设置安全证书权限

在我们演示项目的需求列表中,有一个需求是不同的用户只能访问S3对象存储服务中属于自己的文件。实现该需求有不同的方法,我们这里采用方法的是限制移动客户端使用的AWS 临时安全证书的S3访问权限。在AWS STS AssumeRole 方法中有两个参数可以设置返回的临时安全证书的权限:一个是临时安全证书角色Arn值,一个是附加的Policy字符串。

在我们演示项目的实现过程中,我们为创建的临时安全证书角色分配了如下权限策略,保证AWS STS服务返回的临时安全证书拥有指定S3存储桶的必要操作权限。

{

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

    "Statement": [

        {

            "Effect": "Allow",

            "Action": "s3:ListBucket",

            "Resource": "arn:aws-cn:s3:::tvm-examplebucket"

        },

        {

            "Effect": "Allow",

            "Action": [

                "s3:GetObject",

                "s3:PutObject",

                "s3:DeleteObject"

            ],

            "Resource": "arn:aws-cn:s3:::tvm-examplebucket/*"

        }

    ]

}

请注意,在创建临时安全证书角色的过程中,还需要添加该角色对于之前创建的IAM EC2角色的信任关系。否则TVM服务器端组件在执行AssumeRole方法时候,AWS系统会提示当前用户没有对临时安全证书角色执行AssumeRole操作的权限。

接下来我们将利用模板文件动态地构造附加的Policy,目的是限制每个登录用户只能够访问自己目录下的S3资源。

模板文件的格式如下:

{

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

    "Statement": [

        {

            "Effect": "Allow",

            "Action": "s3:ListBucket",

            "Resource": "arn:aws-cn:s3:::tvm-examplebucket"

        },

        {

            "Effect": "Allow",

            "Action": [

                "s3:GetObject",

                "s3:PutObject",

                "s3:DeleteObject"

            ],

            "Resource": "arn:aws-cn:s3:::tvm-examplebucket/__USERNAME__/*"

        }

    ]

}

以下的例子代码利用登录用户名替换模板中的“__USERNAME__”,构造出指定用户的权限Policy。

代码片段来自于TVM组件的com.amazonaws.tvm.TemporaryCredentialManagement.java源文件。

protected static String getPolicyObject( String username ) throws Exception

{

    // Ensure the username is valid to prevent injection attacks.

    if ( !Utilities.isValidUsername( username ) )

    {

        throw new Exception( "Invalid Username" );

    }

    else

    {

        return Utilities.getRawPolicyFile()

                        .replaceAll( "__USERNAME__", username );

    }

}

权限分级控制

在本演示系统中,用于开发和部署TVM系统的IAM用户、最终运行TVM系统的EC2实例对应的IAM角色和移动客户端所获得的临时安全证书分别拥有不同大小的权限,实现了很好的权限分级控制。

移动客户端临时安全证书的过期问题处理

在前面我们介绍的TVM系统的基本流程里面,移动客户端应用在登录成功后,TVM组件将直接返回临时安全证书。而实际的实现过程要比这复杂一些,主要是为了解决移动客户端获取的临时安全证书过期后的自动更新问题。


TVM系统的完整工作流程如下:

1) 用户通过移动客户端输入账号和密码,登录系统。

2) TVM查询用户数据库,校验账号和密码组合的合法性,创建并返回代表当前用户会话的Key值给移动客户端。

3) 移动客户端在本地缓存获取的会话Key。移动客户端利用本地保存的会话Key和用户动态ID向TVM系统发起请求,申请临时安全证书。

4) TVM系统校验移动客户端用户身份和会话Key,访问AWS STS服务,请求分配临时安全证书,TVM将获取的临时安全证书返回移动客户端。

5) 移动客户端在本地缓存获取的临时安全证书。移动客户端使用本地保存的临时安全证书,持续调用AWS S3 API,执行文件的上传、列表和下载等操作。

关于移动客户端获取临时安全证书,请注意下面的细节:

  • 在临时安全证书有效时间范围内,移动客户端可以直接使用本地保存的临时安全证书访问AWS 服务,比如S3存储桶。
  • 一旦临时安全证书过期,移动客户端需要凭借本地保存的用户会话Key和动态用户ID向TVM系统再次申请临时安全证书,不需要再提供用户名和密码信息。
  • 如果是刚刚启动移动客户端或者TVM用户会话Key已经失效,移动客户端需要执行上述完整的登录和临时安全证书获取过程。

下面的代码片段演示如何登录TVM系统,获取当前用户的会话Key。

代码片段来自于安卓移动客户端组件的com.amazonaws.tvmclient.AmazonTVMClient.java源文件。

public Response login( String username, String password ) {

    Response response = Response.SUCCESSFUL;

    if ( AmazonSharedPreferencesWrapper.getUidForDevice( this.sharedPreferences ) == null ) {

        String uid = AmazonTVMClient.generateRandomString();

        LoginRequest loginRequest = new LoginRequest(this.endpoint,

                                                     this.useSSL,

                                                     this.appName,

                                                     uid,

                                                     username,

                                                     password );

 

        ResponseHandler handler = new LoginResponseHandler( loginRequest.getDecryptionKey() );

        response = this.processRequest( loginRequest, handler );

 

        if ( response.requestWasSuccessful() ) {

            AmazonSharedPreferencesWrapper.registerDeviceId(this.sharedPreferences,

                                                            uid, 

                                                            ((LoginResponse)response).getKey());

            AmazonSharedPreferencesWrapper.storeUsername( this.sharedPreferences, username );                       

        } 

    }

    return response;

}

下面的代码片段演示如何使用当前用户的会话Key和动态用户ID访问TVM系统,更新本地保存的临时安全证书。

代码片段来自于安卓移动客户端组件的com.amazonaws.demo.personalfilestore.AmazonClientManager.java和com.amazonaws.tvmclient.AmazonTVMClient.java源文件。

public Response validateCredentials() {

    Response ableToGetToken = Response.SUCCESSFUL;

    if (AmazonSharedPreferencesWrapper.areCredentialsExpired( this.sharedPreferences ) ) {

        //清空本地保存的过期临时安全证书   

        clearCredentials();      

        AmazonTVMClient tvm =

            new AmazonTVMClient(this.sharedPreferences,

                                PropertyLoader.getInstance().getTokenVendingMachineURL(),

                                PropertyLoader.getInstance().getAppName(),

                                PropertyLoader.getInstance().useSSL() );

        if ( ableToGetToken.requestWasSuccessful() ) {

            ableToGetToken = tvm.getToken();           

        }

    }

    if (ableToGetToken.requestWasSuccessful() && s3Client == null ) {        

        AWSCredentials credentials =

            AmazonSharedPreferencesWrapper.getCredentialsFromSharedPreferences(

                this.sharedPreferences );

        s3Client = new AmazonS3Client( credentials );

        s3Client.setRegion(Region.getRegion(Regions.CN_NORTH_1));

    }

    return ableToGetToken;

}

 

public Response getToken() {

    String uid = AmazonSharedPreferencesWrapper.getUidForDevice( this.sharedPreferences );

    String key = AmazonSharedPreferencesWrapper.getKeyForDevice( this.sharedPreferences );

    Request getTokenRequest = new GetTokenRequest( this.endpoint, this.useSSL, uid, key );

    ResponseHandler handler = new GetTokenResponseHandler( key );

 

    GetTokenResponse getTokenResponse =

        (GetTokenResponse)this.processRequest( getTokenRequest, handler ); 

 

    if ( getTokenResponse.requestWasSuccessful() ) {

        AmazonSharedPreferencesWrapper.storeCredentialsInSharedPreferences(

            this.sharedPreferences,                                                                    

            getTokenResponse.getAccessKey(),                                                                    

            getTokenResponse.getSecretKey(),                                                                                   

            getTokenResponse.getSecurityToken(),                                                                    

            getTokenResponse.getExpirationDate() );

    }

 

    return getTokenResponse;

}

移动客户端和TVM系统安全通信设计

开发者如果需要移动客户端应用在非安全的互联网上直接与TVM系统通信,比如直接使用HTTP而非HTTPS发送登录请求和接收临时安全证书,开发者还需要自己实现一定程度的消息加密解密过程,避免敏感信息比如会话Key或临时安全证书内容在传输过程中被泄密。

演示效果

用户通过手机客户端注册新账号,执行完成登录操作后,就可以上传,查看和删除属于自己的图片文件。上传文件过程支持用户输入文本内容由系统自动产生上传文件和直接从手机客户端选择需要上传的图片文件。


通过查看AWS S3存储桶内容,我们可以看到每个用户上传的图片或文本文件都保存在属于该用户自己的S3存储桶路径下面:

在TVM系统DynamoDB用户数据库的用户表中保存了用户名、用户动态ID和加密的用户密码信息:

在TVM系统DynamoDB用户数据库的设备表中保存了用户的会话Key值:

例子源码

TVM系统服务器端源码

https://s3.cn-north-1.amazonaws.com.cn/mwpublic/projects/tvm/TVMServer.zip

安卓客户端源码

https://s3.cn-north-1.amazonaws.com.cn/mwpublic/projects/tvm/TVMAndroidClient.zip

参考链接

http://aws.amazon.com/articles/4611615499399490

https://aws.amazon.com/code/Java/8872061742402990

http://aws.amazon.com/code/4598681430241367

http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/IAM_Introduction.html

http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles.html

http://docs.aws.amazon.com/zh_cn/STS/latest/UsingSTS/Welcome.html

http://docs.aws.amazon.com/zh_cn/STS/latest/APIReference/Welcome.html

敬请关注

在移动应用设计开发过程中,开发者除了完全靠自己开发实现用户注册和管理功能外,还可以考虑与主流社交媒体身份提供商实现联合身份认证,让已经拥有这些社交媒体身份提供商注册账号的用户能够顺利访问其移动应用。AWS Cognito服务已经支持与Google、Facebook、Twitter 或 Amazon等国际知名社交媒体身份提供商的联合身份认证。后续我们会陆续推出如何与微信、QQ和微博等国内主要社交媒体的联合身份认证方案探讨。

作者介绍:

蒙维

亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构咨询和设计,有超过十年以上电信行业和移动互联网行业复杂应用系统架构和设计经验,主要擅长分布式和高可用软件系统架构设计,移动互联网应用解决方案设计,研发机构DevOps最佳实施过程。

 

为AWS北京区管理控制台集成ADFS访问

原英文链接:http://blogs.aws.amazon.com/security/post/Tx71TWXXJ3UI14

在我们使用AWS的过程中, AWS IAM 是我们接触的第一个服务, 它具有强大的功能,可使您在AWS IAM中通过管理用户, 用户组, 策略, 角色, 证书, 密钥等来灵活而精确的控制对AWS 服务和资源的访问和权限. 同时在很多企业内部, 一般都已经部署了自己的用户管理及授权系统, 如何将AWS的用户管理及授权纳入现有系统则成为企业的想要解决的一个问题. 本文将介绍如何将企业内部Windows活动目录(Active Directory)和AWS通过ADFS(Active Directory Service) 进行集成, 从而实现在活动目录中管理用户对AWS服务和资源的访问和授权.

在AWS IAM中, 我们提供了对SAML的支持, 这个功能可以让我们可以和支持该标准的身份提供商进行联合从而实现单点登陆. 对于很多使用微软活动目录的企业, 我们可以使用Windows自带的ADFS进行和AWS IAM的集成.

工作原理:

在我们进行详细配置之前, 可以先看一下工作原理:

1.       首先用户访问和AWS做了集成的ADFS站点 (https://ADFS/adfs/ls/IdpInitiatedSignOn.aspx)

2.       用户在登陆页面输入用户名及密码, 提交以后ADFS将联系AD进行用户验证

3.       用户浏览器收到ADFS返回的SAML 断言

4.       用户浏览器将用户断言Post到AWS的Sign-in SAML终结点 (https://signin.amazonaws.cn/saml), Sign-in将调用AssumeRoleWithSAML API接口请求临时安全凭证并使用其构建管理控制台的登陆链接

5.       用户浏览器转向使用构建的登陆链接进行登陆

配置活动目录:

1.       在活动目录中及建立用户adfsuser, 邮件地址设为adfsuser@examplecom

2.       在活动目录中建立两个组AWSBJS-Admin, AWSBJS-ReadOnly, 这两个组会和AWS中新建的角色进行匹配

3.       将用户adfsuser添加到AWSBJS-Admin, AWSBJS-ReadOnly这两个组中

安装部署Active Directory Federation Service

我们可以参考如下的文档部署ADFS服务

https://technet.microsoft.com/en-us/library/dn486775.aspx

导出SAML Metadata Document

访问ADFS服务器并导出 SAML Metadata Document (将ADFS换成你ADFS服务器的名称)

https://ADFS/FederationMetadata/2007-06/FederationMetadata.xml

配置AWS

1.       登录 AWS管理控制台https://console.amazonaws.cn/

2.       在IAM服务中, 点击身份提供商, 选择SAML, 导入从ADFS服务器上导出的SAML Metadata

3.       记录下提供商ARN记录

4.       新建IAM 角色ADFSBJS-Admin和ADFSBJS-ReadOnly [注意选择 授予 SAML 提供商 Web 单点登录 (Web SSO) 访问权限, 这两个角色会和活动目录中的新建的用户组AWSBJS-Admin和AWSBJS-ReadOnly对应]

5.       记录各个角色的ARN

配置ADFS将AWS作为 信赖方信任

1.       打开ADFS管理界面, 选择信任关系-信赖方信任

2.       右键点击信赖方信任, 点击 添加信赖方信任

3.       点击 启动

4.       选择 导入有关在线或在本地网络发布的信赖方的数据, 在联合元数据地址栏输入以下地址,点击 下一步

https://signin.amazonaws.cn/static/saml-metadata.xml

5.       在 显示名称 中输入AWS China, 然后点击下一步

6.       选择 不配置多重身份验证, 点击 下一步:

7.       选择 允许所有用户访问此信赖方, 点击下一步

8.       点击下一步:

9.       点击 关闭

10.    点击 关闭, 并打开编辑声明规则

为AWS 信赖方信任 建立 声明规则

1.       在编辑声明规则中, 点击 添加规则

2.       选择 转化传入声明, 点击下一步

3.       声明规则名称使用 NameId, 传入声明类型 选择 Windows帐户名, 传出声明类型 选择 名称ID, 传出名称ID格式 选择 永久标识符, 点击完成

4.       再次点击 添加规则

5.       选择以声明方式发送LDAP特性, 点击 下一步

6.       声明规则名称 输入RoleSessionName, 特性存储选择 Active Directory, LDAP特性 选择 E-Mail-Address, 传出声明类型输入 https://aws.amazon.com/SAML/Attributes/RoleSessionName, 点击完成

7.       再次点击 添加规则

 

8.       选择 使用自定义规则发送声明, 点击 下一步

9.       声明规则名称输入 Get AD Groups, 自定义规则输入以下文本 (这一步用来取出登录用户所在的AD用户组, 并将其传入到临时声明 http://temp/variable中), 点击完成

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == “AD AUTHORITY”]

=> add(store = “Active Directory”, types = (“http://temp/variable”), query = “;tokenGroups;{0}”, param = c.Value);

10.    再次点击 添加规则

11.    选择 使用自定义规则发送声明, 点击下一步

12.    声明规则名称 输入 Roles, 自定义规则中输入以下文本 (这部分主要是用来映射AD中的用户组 和 AWS中的角色之间的对应关系, 其中红色部分需要根据我们前面所建的AD用户组名称 和 身份提供商的ARN和角色的ARN调整), 点击完成

c:[Type == “http://temp/variable”, Value =~ “(?i)^AWSBJS-“]

=> issue(Type = “https://aws.amazon.com/SAML/Attributes/Role”, Value = RegExReplace(c.Value, “AWSBJS-“, “arn:aws-cn:iam::761602622223:saml-provider/ADFS,arn:aws-cn:iam::761602622223:role/ADFSBJS-“));

13.    重新启动 Active Directory Federation Service

测试配置效果

1.       访问https://ADFS/adfs/ls/IdpInitiatedSignOn.aspx (将ADFS换成你ADFS服务器的名称)

2.       输入用户名和密码

3.       验证以后, 服务器将根据它所在的组返回它拥有的角色, 用户选择不同的角色就可以拿到不同角色的权限

4.       登录以后在右上角可以看到当前用户及其所使用的角色信息

总结:

上述是将ADFS和AWS管理控制台集成从而实现使用AD账号系统登录访问AWS管理控制台的详细流程. 同时我们还可以通过调整ADFS本身的身份验证策略来实现多重验证等功能.