@liuhui0803
2019-10-21T09:22:16.000000Z
字数 4179
阅读 1859
AWS
安全
云计算
微软
你的AWS帐户需要妥善保护,这不仅是为了保护客户数据,同时也是为了增强应用程序的可用性。对于生产环境中的工作负载这一点尤为重要,我们需要完全确信谁能访问每个账户,可以获得何种级别的权限,并能从整个组织层面上管理用户,而不用分别管理每个系统。无论配置了多少策略和流程,最终总会有人分享自己本不应分享的帐户或安全密钥!通过配合使用SAML Identity Provider和Active Directory则可以有效解决这个问题!
虽然我们已经可以通过一些预配置的选项,例如使用AWS SSO作为SAML提供程序,但这种做法依然需要使用AD Connector将AD扩展到AWS,使其成为AWS Directory Services的一部分,这也意味着我们需要实施VPN或Direct Connect,但这并非始终都是最适合的方法,有时候甚至根本不可行!就算我们将AD扩展到AWS,也无法直接实现AWS SSO,我们还需要使用ADFS构建自己的解决方案。
为了构建这样的解决方案,我们需要使用多种组件:
我打算从较高层面介绍这些组件如何协同工作,因为这其中涉及很多组件和依赖项。
为了成功登录,用户需要访问一个备用URL(例如awsconsole.domain.com),而不能访问传统的控制台URL。该URL会将用户重定向至SAML提供程序,对其进行身份验证,随后允许用户访问特定的AWS帐户。
能否访问AWS帐户,这是由一系列组件共同决定的:用户在AD中隶属的组,以及AWS中创建的IAM角色。AD中的组需要具备与IAM角色相关的名称。随后IAM角色还必需具备必要的权限,以便让用户在通过身份验证后获得所需的权限级别。
IAM角色与“用户”不同,并不包含访问密钥和机密密钥,而是会生成一组临时凭据,这些凭据在过期前可使用一段时间,在过期后则要重新生成。如果希望详细理解该过程的工作原理,建议阅读STS(安全令牌服务)文档。
这个解决方案不仅适用于控制台,也适用于CLI。通常我会使用一款名为saml2aws的工具来简化身份验证过程,借此实现以编程方式进行的访问,现在,则可以用它来取代硬编码的IAM。
另外还要注意,该解决方案可支持用于多个帐户!
SAML基本概念
在深入介绍配置过程前,首先有必要简要了解一些与SAML有关的基本概念和术语。如果你以前从未使用过SAML,那么更有必要了解一下这些术语:
此处需要注意,IdP和SP绝对不会直接通信,发生的所有通信都是通过最终用户的浏览器进行的。IdP和SP只是能简单地感知对方的存在,如下所示:
来源:https://en.wikipedia.org/wiki/SAML_2.0
首先我们需要在ADFS中配置一个新的依赖方信任,为此可以使用ADFS中的RPT向导。AWS通过一个XML文件公开提供了自己的SAML元数据,该XML文件可以直接引用到你自己的IdP中。在添加了诸如联合身份验证元数据和RPT名称等初始信息后,即可使用默认设置完成向导的其他操作。
联合身份验证元数据地址:
https://signin.aws.amazon.com/static/saml-metadata.xml
向导操作完成后,应该可以在你自己的ADFS服务器的RPT列表中看到一项有关AWS的内容。随后我们需要在ADFS中配置声明规则,这些规则可以将需要身份验证的用户的相关信息作为断言的一部分发送给AWS。右键点击AWS RPT并选择“编辑声明规则”即可。
将Windows帐户名映射给发送给AWS的断言中的NameID一节。
规则名称:NameId
声明规则模板:转换传入声明
将用户的电子邮件地址映射至发送给AWS的断言中的RoleSessionName特性。
规则名称:RoleSessionName
声明规则模板:以声明方式发送LDAP特性
传出声明类型:https://aws.amazon.com/SAML/Attributes/RoleSessionName
获取用户所属的AD组列表。这样一旦用户的AWS帐户成功通过了身份验证,就可以使用这些AD组。
规则名称:Get AD Groups
声明规则模板:使用自定义规则发送声明
自定义规则:
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);
将AD组列表转换为与AWS中所创建的IAM角色相匹配的格式。
规则名称:Group Transformer
声明规则模板:使用自定义规则发送声明
自定义规则:
c:[Type == "http://temp/variable", Value =~ "(?i)^AWS-([\d]{12})-"]
=> issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "AWS-([\d]{12})-", "arn:aws:iam::$1:saml-provider/ADFS,arn:aws:iam::$1:role/AWS-"));
设置会话令牌的有效期。我们通常将其设置为10小时(对于典型的工作日来说已经足够长了)。
规则名称:SessionDuration
声明规则模板:使用自定义规则发送声明
自定义规则:
=> issue(Type = "https://aws.amazon.com/SAML/Attributes/SessionDuration", Value = "36000");
ADFS配置完毕后,该配置我们的AWS帐户了。对于任何希望使用SAML验证身份的帐户,都需要执行下列操作(或作为帐户自动化操作过程的一部分来执行)。
打开IAM > Identity Providers,新建一个提供程序,随后向AWS提供如下信息:
随后需要新建一个IAM角色。用户登录AWS帐户时需要使用该角色。请打开IAM > Roles,随后新建一个角色。
接下来需要为该角色分配权限,借此用户才能以这个角色的身份执行各种操作。本例中将提供ReadOnlyAccess权限。
在最后一个界面上,可以将该角色命名为AWS-GavinSandbox-ROA。角色名称中一定要包含“AWS”字样,因为我们的组转换信息中需要包含该字样。
随后我们需要在Active Directory中创建与AWS帐户中角色信息相匹配的用户组。组名称的格式必需为AWS-<ACCOUNTID>-<ROLENAME>
,请酌情替换Account ID和IAM角色名称。
组创建完毕后,我们需要为其分配用户,例如此处分配了我本人:
这一步并非必需,但可以让通过SAML访问AWS帐户的过程变得更简单。借此可以让用户访问一个URL(例如awsconsole.domain.com)来访问AWS控制台,而不需要手工访问你的IdP然后选择SP。
在你的某一个AWS帐户(例如组织内部,配置了特定SCP策略的核心基础架构相关帐户)中创建一个S3 Website Bucket,将其命名为awsconsole.domain.com(请酌情替换domain.com)。将该Bucket配置为静态网站托管,然后选择执行重定向的选项:
目标:fs.domain.com/adfs/ls/idpinitiatedsignon.aspx?logintorp=urn:amazon:webservices
协议:https
创建完成后,在DNS中新建一条记录,借此将awsconsole.domain.com指向S3 Bucket。
接下来可以开始试运行一下了。请在浏览器中输入URL:awsconsole.domain.com。随后首先会看到浏览器窗口将你重定向至IdP并自动进行身份验证,或要求登录(具体行为取决于配置)。
随后可以看到自己能够访问的帐户列表,选择一个角色并点击登录。
假设一切正常无误,接下来就可以用刚才选择的角色成功登录自己的帐户了!
为了进一步提高该解决方案的安全性,我们还可以考虑实施MFA,借此进一步降低他人AD帐户被攻陷,以至于攻击者借此访问多个系统的风险。
上述操作看起来似乎很繁琐,并且最初需要做大量工作,但长远来看,以后只需要添加额外的AD组并配置AWS帐户就够了。最终这些操作还可以实现自动化,为此需要使用我开发的一个虽然简陋但已实用的Serverless工具:account factory,当然,市面上也有很多其他类似的工具可供选择。
本文最初发布于The Startup博客,原作者Gavin Lewis,经原作者授权由InfoQ中文站翻译并分享。阅读英文原文:Securing your AWS Accounts with SAML Authentication。