AWS支持使用安全保证标记语言(SAML)2.0进行身份集成。通过SAML,可以将AWS帐户配置为与身份提供者(IdP)集成。

一旦配置,你组织的身份提供商就会对你的联合用户进行验证和授权,然后联合用户可以使用单点登录方法登录到AWS管理控制台。这不仅可以使你的用户免于记住另一个用户名和密码,也是简化了管理员的身份管理过程。当你的联合用户想访问AWS管理控制台,这种方法是有效的。但是当他们想使用AWS CLI或以程序方式调用AWS API时,将会怎么样呢?

在本文中,我将向你展示如何对你的用户实施联合的API与CLI访问。本帖中提供的举例使用了AWS Python SDK工具和一些附加的客户端侧的集成代码。如果你有用户需要这种访问控制,实施该方案可以使你对这些用户的管理轻松自如。

让我们从快速地了解我们的目标开始。

从上面的输出结果中我们清楚地看到了什么?

1. 系统提示联合用户输入Active Directory(动态目录)证书。这些证书用来与配置的IdP进行比较以对用户进行验证和授权。

2. 系统检查返回的SAML断言,确定用户被授权承担的IAM(身份及访问管理)角色。用户选择了她期望的角色后,系统使用AWS STS(安全令牌服务)提取临时的安全证书。

3. 系统自动地将这些证书写入她本地的AWS证书文件,她可以开始发出AWS API或CLI调用指令。

4. 得到该样例,为你的组织对样例进行定制后,你就可以在保持AWS IAM服务提供的控制的同时,使用组织的证书来提高你的AWS API和CLI界面的能力和自动化程度。

本帖将会集中讲述如何使用微软动态目录联合服务(AD FS)。但是如果你正在使用其他供应商的同类产品,请不要感到失望因为基本的组件应该可以与其他常见的IdP配合运转的。

为了能够紧跟本帖的讲述,你必须已经:

入门

1. 使用你的组织证书将AD FS正确地与你的AWS账户进行了集成,以便能够访问控制台。如果你需要设置说明,请参考Enabling Federation to AWS using Windows Active Directory, ADFS, and SAML 2.0。

2. 已在本地工作站安装了新版本(2.36或更新)的AWS Python SDK工具。

3. 获取了最小限度的AWS证书文件(例如:~/.aws/credentials),并将文件中的如下内容调整到你首选的区域和输出格式。

重要提示:AWS访问密钥对并没有在上面的结构中配置因为最初的AWS STS调用是由值得信任的IdP返回的SAML断言进行验证的。所有后续的API/CLI调用都是由包含在AWS STS令牌中的密钥对进行验证的。想要获取更多信息,请参考Giving AWS Console Access to Federated Users Using SAML

首先,你需要安装不属于Python核心发行版的两个模块,具体说,就是beautifulsoup4和requests-ntlm。有若干种方法可以安装着两个模块,但是包含在Python 2.7.9或更新版本中的pip工具,使模块安装变得很容易。你只需运行如下两个命令即可:

[default] output = json region = us-west-2 aws_access_key_id = aws_secret_access_key =

首先运行下面的命令:

<u>pip install beautifulsoup4</u>

然后运行下面的命令:

pip install requests-ntlm

你应该会得到一些与如下截图类似的输出结果:

AWS联合过程利用IdP发起的登录方法。在最后的准备步骤中,你需要确定具体的被用来引发登录的URL。以基本的IdP引发登录的URL为起点(该URL就是你用来联合访问SAML依赖各方的URL,SAML依赖各方包括AWS管理控制台)。在本例中,我使用的是AD FS 2.0。在该版本中,URL的格式为ofhttps://<fqdn>/adfs/l。如果我将该URL输入浏览器的地址栏,我将会看到一个网站选择页面,如下图所示:

为了构造你所需的URL,将原来的IdP引发登录URL与查询字符串?loginToRp=urn:amazon:webservices连接。构造好的URL应呈现的形式是ofhttps://<fqdn>/adfs/l?loginToRp=urn:amazon:webservices。保存该URL因为在后面的叙述中它将被称为idpentryurl变量。如果你将这个串联的URL输出浏览器的地址栏,你应该仍然可以实现AD FS IdP引发登录过程。但是,你绕过了网站选择页面,在验证完演练所需的URL后直接进入AWS管理控制台。如果感兴趣的话,你可以访问Microsoft’s website去查看关于查询字符串的文档。

重要提示:务必密切注意URL中主机名称的大写。AD FS在验证过程中会使用主机名称,任何在大小写方面的不匹配都会导致验证失败。

检查代码

既然你已经浏览了上面“入门”部分的步骤,你可以开始组合控制联合API与CLI访问的集成代码了。我将会详细地解释这一过程以便你可以跟随我的节奏。首先,让我们进行一些基本的导入和变量设置。

#!/usr/bin/python import sys import bo import bo import requests import getpass import ConfigParser import base64 import xml.e as ET from bs4 import BeautifulSoup from os.path import expanduser from urlparse import urlparse, urlunparse from requests_ntlm import HttpNtlmAuth ########################################################################## # Variables # region: The default AWS region that this script will connect # to for all API calls region = 'us-west-2' # output format: The AWS CLI output format that will be configured in the # saml profile (affects subsequent CLI calls) outputformat = 'json' # awsconfigfile: The file where this script will store the temp # credentials under the saml profile awsconfigfile = '/.aws/credentials' # SSL certificate verification: Whether or not strict certificate # verification is done, False should only be used for dev/test sslverification = True # idpentryurl: The initial URL that starts the authentication process. idpentryurl = 'https://<fqdn>/adfs/l?loginToRp=urn:amazon:webservices' ##########################################################################

将上述代码中的变量调整为针对你的具体的区域(如us-west-2,us-east-1等等)和格式喜好(例如json,文本,或表格),然后插入本帖中上一部分变量idpentryurl的值。

基本环境搭建起来后,提示用户,从标准输入中检索用户的证书。在本帖的后面我将会讨论我们是如何支持其他的证书形式的。

# Get the federated credentials from the user print "Username:", username = raw_input password = ge print ''

位于第一行打印语句“Username”后面的逗号可能看起来像是一个缺陷,实际上它是Python为了防止第一行打印语句添加换行符而使用的小技巧。你也将会注意到getpass这一方法的使用,这一方法是为了防止密码被显示在输出结果中。

下一步,我们使用Python请求模块组合验证信息,用公式表示向IdP发送的HTTPS请求,正如下面的片段所示。假设验证成功,AD FS返回的响应消息会包含SAML断言。

# Initiate session handler session = reque # Programatically get the SAML assertion # Set up the NTLM authentication handler by using the provided credential = HttpNtlmAuth(username, password, session) # Opens the initial AD FS URL and follows all of the HTTP302 redirects response = (idpentryurl, verify=sslverification) # Debug the response if needed #print )

截止到目前,IdP响应已经安全到手了。所以,然让我们覆盖和废弃我们原来用来存储用户名和密码的变量,因为我们不再需要它们了。作为一种更高级别的语言,Python并不像C语言那样可以提供直接的内存操作来覆盖这些变量。但是Python的这个特点可以确保证书不到处游荡(到处被验证)。

# Overwrite and delete the credential variables, just for safety username = '##############################################' password = '##############################################' del username del password

正如我前面提到的,我们需要的SAML断言可以在IdP的响应消息中找到。下面的代码使用BeautifulSoup模块来提取SAML断言。

# Decode the response and extract the SAML assertion soup = BeautifulSoup.decode('utf8')) assertion = '' # Look for the SAMLResponse attribute of the input tag (determined by # analyzing the debug print lines above) for inputtag in ('input'): i('name') == 'SAMLResponse'): #prin('value')) assertion = in('value')

这个片段只是循环访问所有的HTML输入标签直到它找到名称为SAMLResponse的标签。我们所寻找的Base64编码的断言包含在该标签的取值属性中。在继续下一步前,我们需要深入一层处理SAML验证响应消息,提取该用户被授权的角色列表。该列表存储在SAML属性named中,正如下面的代码所示。

# Parse the returned assertion and extract the authorized roles awsroles = root = ET.fromstring(assertion)) for saml2attribute in root.iter('{urn:oasis:names:tc:SAML:2.0:assertion}Attribute'): if ('Name') == ''): for saml2attributevalue in ('{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue'): aw) # Note the format of the attribute value should be role_arn,principal_arn # but lots of blogs list it as principal_arn,role_arn so let's reverse # them if needed for awsrole in awsroles: chunks = aw(',') if'saml-provider' in chunks[0]: newawsrole = chunks[1] + ',' + chunks[0] index = aw(awsrole) aw(index, newawsrole) aw(awsrole)

在上面的第一个环中,我在使用Pythonxml.e模块解析SAML断言。尽管断言看起来不是特别地整齐,但是明确的名字空间和名称使我们的寻找变得相对简单。

在第二个环中,代码只是在做一些主动的错误预防,以确保角色中包含的ARN(亚马逊资源名称)排序正确。

现在我们知道了用户被授权承担的角色。下一步,代码询问用户他们想要使用的角色。

# If I have more than one role, ask the user which one they want, # otherwise just proceed print "" if len(awsroles) > 1: i = 0 print "Please choose the role you would like to assume:" for awsrole in awsroles: print '[', i, ']: ', aw(',')[0] i += 1 print "Selection: ", selectedroleindex = raw_input # Basic sanity check of input if int(selectedroleindex) > (len(awsroles) - 1): print 'You selected an invalid role index, please try again' (0) role_arn = awsroles[int(selectedroleindex)].split(',')[0] principal_arn = awsroles[int(selectedroleindex)].split(',')[1] else: role_arn = awsroles[0].split(',')[0] principal_arn = awsroles[0].split(',')[1]

如果用户只要一个角色,该角色会自动被使用。否则,系统会提示用户从一个简单的枚举列表中选择他们想要使用的角色。

现在,事情变得非常简单。因为我们已经检索了SAML断言,提取了各种ARN。我们只需要调用标准的AWS STS服务来请求AWS临时安全证书。这真的是整个过程的关键。我们已经做了所有的努力直到现在为下面简单的AssumeRolewithSAML API调用准备各种参数。

# Use the assertion to get an AWS STS token using Assume Role with SAML conn = bo.connect_to_region(region) token = conn.assume_role_with_saml(role_arn, principal_arn, assertion)

重要提示:SAML断言来自于已配置的值得信任的IdP,它的作用就是为这次API调用充当验证证书。

现在我们已经从AWS STS获得了证书,下一步就是将这些证书插入AWS证书文件中的一个特定的文件,正如下面的片段所示。通过这一步,你将能够使用临时安全证书来进行任意次数的API或CLI调用,直到证书过期。

# Write the AWS STS token into the AWS credential file home = expanduser("~") filename = home + awsconfigfile # Read in the existing config file config = Con con(filename) # Put the credentials into a specific profile instead of clobbering # the default credentials if not con('saml'): con('saml') con('saml', 'output', outputformat) con('saml', 'region', region) con('saml', 'aws_access_key_id', ) con('saml', 'aws_secret_access_key', ) con('saml', 'aws_session_token', ) # Write the updated config file with open(filename, 'w+') as configfile: con(configfile)

在这个代码片段中,我只是在使用变量组合来确定AWS证书文件的位置,读取文件,添加或更新名称为saml的文件,并将变动写回文件。

最后,代码使联合用户对刚刚发生的过程有一个大概的了解。

# Give the user some basic info as to what has just happened print '\n\n----------------------------------------------------------------' print 'Your new access key pair has been stored in the AWS configuration file {0} under the saml profile.'.format(filename) print 'Note that it will expire at {0}.'.forma) print 'After this time you may safely rerun this script to refresh your access key pair.' print 'To use this credential call the AWS CLI with the --profile option . aws --profile saml ec2 describe-instances).' print '----------------------------------------------------------------\n\n'

如果你的自动化过程是基于CLI的,你可以直接跳到下个部分“将代码进行综合”。此外,如果你的自动化过程是基于API的,当你进行连接时,你只能使用临时安全证书

# Use the AWS STS token to list all of the S3 buckets s3conn = bo.connect_to_region(region, aws_access_key_id=, aws_secret_access_key=, security_token=) buckets = print 'Simple API example listing all s3 buckets:' print(buckets)

在实践中,将这些附加的API调用放置在一个单独的脚本中,并设置该脚本利用我们前面设置的证书文件,是一个更好的形式。但是这种实践的关键是从AWS STS接收的证书正用于验证API调用。

将代码进行综合

当你将所有的代码综合起来后,你会看到下面的输出结果。

janedoe@Ubuntu64:/tmp$ . Username: AD\janedoe Password: **************** Please choose the role you would like to assume: [ 0 ]: arn:aws:iam::012345678987:role/ADFS-Administrators [ 1 ]: arn:aws:iam::012345678987:role/ADFS-Operators Selection: 1 ---------------------------------------------------------------Your new access key pair has been stored in the aws configuration file /home/janedoe/.aws/credentials under the saml profile. Note that it will expire at 2015-05-26T17:16:20Z. After this time you may safely rerun this script to refresh your access key pair. To use this credential call the aws cli with the --profile option . aws --profile saml ec2 describe-instances). --------------------------------------------------------------- Simple API example listing all s3 buckets: [<Bucket: mybucket1>, <Bucket: mybucket2>, <Bucket: mybucket3>, <Bucket: mybucket4>, <Bucket: mybucket5>]

从上面的输出结果中我们清楚地看到了什么?

然后你就可以通过引用saml文件来进行后续的API或CLI调用,正如下面的输出结果所示。

janedoe@Ubuntu64:/tmp$ aws --profile saml --output text s3api list-buckets BUCKETS 2014-09-09T17:11:48.000Z mybucket1 BUCKETS 2014-11-03T18:27:35.000Z mybucket2 BUCKETS 2014-08-13T02:45:28.000Z mybucket3 BUCKETS 2015-01-14T17:53:47.000Z mybucket4 BUCKETS 2015-05-19T19:23:25.000Z mybucket5 OWNER myowner 128abcedf111aa33cc44ddee5512345abcd6fff4eed

最后要说的是,SAML具有以浏览器为导向的特性。这一特性就要求一些额外的代码和一些程序,但是它确实完成了目标,即为API和CLI调用开启基于联合的验证!

如果你使用其他的身份提供商或验证机制

如果你正在使用AD FS以外的其他IdP,不要因为该博客帖未包含针对你的解决方案而失望。我选择使用Python模块集成技术来模仿浏览器行为的原因是,该技术可扩展到几乎所有的IdP方案。

相似地,如果你正在使用其他的验证机制,如Kerberos,X.509证书,或MFA(多因子验证),在Python请求模块中有额外的处理办法。在你使基础环境搭建好后,这些处理办法可以用来加强上面的举例。

( 翻译/吕东梅 责编/王鑫贺 )

订阅“AWS中文技术社区”微信公众号,实时掌握AWS技术及产品消息!

AWS中文技术社区为广大开发者提供了一个Amazon Web Service技术交流平台,推送AWS最新资讯、技术视频、技术文档、精彩技术博文等相关精彩内容,更有AWS社区专家与您直接沟通交流!快加入AWS中文技术社区,更快更好的了解AWS云计算技术。

1.《关于111aa我想说如何使用SAML 2.0和AD FS部署API共同控制CLI访问》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《关于111aa我想说如何使用SAML 2.0和AD FS部署API共同控制CLI访问》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/yule/1956897.html