一. 前言
在AWS,我们始终坚持以客户为中心并不遗余力地帮助客户取得成功。因此,当我们找到一种有趣且高效的方法,而且是用AWS服务组合来创建有价值的功能时,我们希望其他客户也能够了解它,这样他们也可以从中获益。这里我们分享的一个例子,即使用AWS支持API、EventBridge、Lambda、Athena、S3和QuickSIght创建了一个跨帐户支持案例面板。跨帐户案例面板是AWS提供的支持API和一系列工具组合的自动化运维范例,它允许用户在单个位置查看多个帐户的案例详细信息。
AWS客户打开支持案例是为了解决问题,获取更多关于AWS服务的信息,即用户在设计应用程序时遇到问题,通过案例来获取相应的指导分析和解决方案等。而对于商业和企业支持客户,有无数的用户可以打开无限数量的案例,因此,任何给定的客户在任何给定的时间都可能有数十个甚至数百个支持案例,特别是有的大型客户或合作伙伴可能每月就会开启数百甚至数千支持案例,对于任何一个客户或合作伙伴来说,集中查看所有用户打开的案例并了解其情况是很有价值的,能帮助他们方便的参考当前案例和过往案例的概况,同时也易于与组织内的其他人分享案例中的经验教训以提高生产力,而AWS的合作伙伴可以利用面板的观察,准确掌控案例开启和处理的状况来提高案例的处理质量。(如下是面板示例)
二. 方案概览
这里是展示了一个在跨账户下实现中心化案例管理的面板设计应用架构,其中集成了AWS Support API、Lambda、Athena、Quicksight等服务组件:
此方案布署前需要进行一些角色的初步配置,即为了能够具备跨账户描述支持案例内容的权限,需要在子帐户中创建了一个IAM角色。然后允许它们被主账户IAM角色用assume role方式来访问。
三. 具体实现过程
1) 配置sub-account的role
在sub-account里创建CF stack,以便能允许master-account用assume role方式来调用Support API查询案例情况:
Template 的参考文件可以从这里获得。
如上请保持role name不变,并输入master-account的账户ID,然后点Next,直到stack创建完成。
2) Lambda的配置:
创建Lambda:
a) 先创建Lambda的role ex. “masterrole”,其应包含lambda execute、SES、AWS support Access和S3的permission的权限。
b) 选Create Function from ‘Author from Scratch’:
其中用刚建的lambda role来执行。
把如下代码贴入lambda文件:
其中需要修改参数如下:
bucketname(S3桶名),
filename(从s3桶里读取的账户列表文件名) ,
SES_Region(SES区域名), SES_SENDFROM(发送者邮箱)和SES_SENDTO(接受者邮箱),
查询过去多少天(delta#负数)的案例处理情况。
#!/usr/bin/env python
import boto3
import csv
import os
import json
import datetime
#For email
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
def lambda_handler(event, context):
sts_client = boto3.client('sts')
s3=boto3.client('s3')
bucketname = '<bucket name'
filename='path to accountIDs file'
api_region = 'us-east-1'
SES_SENDFROM = '<mail from address>'
SES_SENDTO = '<mail to address>'
SES_REGION = '<SES region name>'
#Read AccountIDs
fileobj= s3.get_object(
Bucket=bucketname,
Key=filename,)
accountid = fileobj['Body'].read().decode('utf-8').splitlines()
f = open('/tmp/case_list.csv', 'w+', newline='\n', encoding='utf-8')
csv_writer = csv.writer(f)
csv_writer.writerow(['case-id', 'status', 'severity','service', 'subject', 'createdtime', 'case-owner', 'account-id'])
for line in accountid:
aid = line.strip()
assumed_role_object = sts_client.assume_role(
RoleArn="arn:aws:iam::"+aid+":role/GetSupportInfoRole",
RoleSessionName="masterrolesession"
)
credentials = assumed_role_object['Credentials']
#Switch Role to execute
case_client = boto3.client(
'support',
region_name = api_region,
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken'],
)
now = datetime.datetime.now()
timeline = (now + datetime.timedelta(days=<delta#>)).strftime("%Y-%m-%dT%H:%M:%S")
case_response = case_client.describe_cases(includeResolvedCases=True,afterTime=timeline)
#Get Case Status
for i in range(len(case_response['cases'])):
case_id = case_response['cases'][i]['displayId']
case_status = case_response['cases'][i]['status']
case_severity = case_response['cases'][i]['severityCode']
case_service = case_response['cases'][i]['serviceCode']
case_subject = case_response['cases'][i]['subject']
case_date = case_response['cases'][i]['timeCreated']
case_owner = case_response['cases'][i]['submittedBy']
fields=[case_id,case_status,case_severity,case_service,case_subject,case_date,case_owner,aid]
print(fields)
csv_writer.writerow(fields)
f.close()
s3.upload_file("/tmp/case_list.csv",bucketname,"casefile/case_list.csv")
#Sending Email
msg = MIMEMultipart()
msg['From'] = SES_SENDFROM
msg['To'] = COMMASPACE.join(SES_SENDTO.split(","))
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = "Case Status"
text = "Find your Case Status Report attached\n\n"
msg.attach(MIMEText(text))
with open("/tmp/case_list.csv", "rb") as fil:
part = MIMEApplication(
fil.read(),
Name="case_list.xlsx"
)
part['Content-Disposition'] = 'attachment; filename="%s"' % "case_list.xlsx"
msg.attach(part)
# Sending Mail notification
ses = boto3.client('ses', region_name=SES_REGION)
result = ses.send_raw_email(
Source=msg['From'],
Destinations=SES_SENDTO.split(","),
RawMessage={'Data': msg.as_string()}
)
c) 增加一个触发器:
可以在lambda配置界面直接增加一个触发器:
同时创建一个新的规则:
触发器规则中设定相应的定期触发时间,让lambda去定时获取相应的case处理情况。
3) Athena的设定:
a) 首先创建一张数据表,建表的SQL语句:
CREATE EXTERNAL TABLE <table name> (
caseid STRING,
status STRING,
severity STRING,
service STRING,
subject STRING,
createdtime STRING,
caseowner STRING,
accountid STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
STORED AS TEXTFILE LOCATION 's3://<S3 bucketname and prefix>'
TBLPROPERTIES ("skip.header.line.count" = "1")
注意:如前面lambda配置,建议把account list文件和生成的案例列表文件放在s3桶下不同的prefix下。
b) 查询数据表做数据验证:
SELECT * FROM <table name> limit 100;
4) Quicksight的配置:
a) 首先新建一个新的数据集:
b) 以上面这个新的数据集创建一个analysis:
c) 最后以pivot table图形类型来创建你自己的案例面板:
除了上面生成案例面板外,也可以通过其它类型图表实现自定义案例状态、类型和紧急程度的其它可视化图表等。
总结
客户越来越多地组织管理多个帐户并要求提供管理多帐户的功能,而集中管理多客户支持案例是您面临的一个挑战吗?如前述内容描述,我们利用自动化运维的方式,通过集成EventBridge、Lambda和QuickSight为您轻松构建可视化面板,如果您觉得会从中获得价值并可以打造自己定制的面板,请参考以上的方案来尝试看是否能够解决。我们也会通过更多类似的案例分享给用户我们更多的经验和方法。
更多内容
更多有关AWS Support SDK及Lambda实现相关内容,请大家参考AWS SDK,STS和Lambda 官方文档::
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/support.html#Support.Client.describe_cases
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-api.html
https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html
https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html
https://docs.aws.amazon.com/cli/latest/reference/support/describe-cases.html
本篇作者