问题描述
我有一个 CloudFormation 模板,它创建了一个像这样的 ElasticBeanstalk 环境:
"ApplicationEnvironment": {
"Type": "AWS::ElasticBeanstalk::Environment","Properties": {
"ApplicationName": {
"Ref": "Application"
},"SolutionStackName": "64bit Amazon Linux 2018.03 v2.11.2 running Java 8","VersionLabel": {
"Ref": "AppVersion"
},"Tier": {
"Name": "WebServer","Type": "Standard"
},"OptionSettings": [
...
{
"Namespace": "aws:elasticbeanstalk:environment","OptionName": "EnvironmentType","Value": "LoadBalanced"
},{
"Namespace": "aws:elasticbeanstalk:environment","OptionName": "LoadBalancerType","Value": "application"
},...
---
"WAF": {
"Type": "AWS::WAFv2::WebACL","Properties": {
"DefaultAction": {
"Type": "BLOCK"
},"Scope": "REGIONAL","VisibilityConfig": {
"CloudWatchMetricsEnabled": "false","MetricName": { "Fn::Join": [ "",[ { "Ref": "AWS::StackName" },"metric-waf" ] ] },"SampledRequestsEnabled": "false"
},"Rules": [
{
"Action" : {
"Type" : "BLOCK"
},"Priority" : 0,"Statement" : {
"ManagedRuleGroupStatement": {
"vendorName": "AWS","Name": "AWSManagedRulesCommonRuleSet"
}
}
}
]
}
},"WAFAssociation": {
"Type" : "AWS::WAFv2::WebACLAssociation","Properties" : {
"ResourceArn" : ???,"WebACLArn" : { "Ref": "WAF" }
}
}
我打算将 Beanstalk ALB 与 WebACL 相关联,但不知道如何引用模板创建的应用程序负载均衡器 ARN。我不能只放入硬编码的 ARN,因为它总是根据模板创建的内容而变化。
有什么方法可以引用 ResourceArn 字段中的 ALB ARN?或者我是否需要在 Beanstalk 选项设置中的某处应用 WebACL?
解决方法
我认为唯一的方法是通过一个自定义资源,它采用 EB env 名称,使用 describe_environment_resources
API 调用来获取 EB env 信息(包括 LA arn),然后返回到你卡住了。
以下是您可以添加到模板中的此类资源的工作示例:
LambdaBasicExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2FullAccess
- arn:aws:iam::aws:policy/AWSElasticBeanstalkFullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
MyCustomResource:
Type: Custom::GetEBLoadBalancerArn
Properties:
ServiceToken: !GetAtt 'MyCustomFunction.Arn'
EBEnvName: !Ref MyEnv
MyCustomFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
Description: "Get ARN of EB Load balancer"
Timeout: 30
Role: !GetAtt 'LambdaBasicExecutionRole.Arn'
Runtime: python3.7
Code:
ZipFile: |
import json
import logging
import cfnresponse
import boto3
logger = logging.getLogger()
logger.setLevel(logging.INFO)
eb = boto3.client('elasticbeanstalk')
ec2 = boto3.client('ec2')
def lambda_handler(event,context):
logger.info('got event {}'.format(event))
try:
responseData = {}
if event['RequestType'] in ["Create"]:
eb_env_name = event['ResourceProperties']['EBEnvName']
response = eb.describe_environment_resources(
EnvironmentName=eb_env_name
)
lb_arn = response['EnvironmentResources']['LoadBalancers'][0]['Name']
logger.info(str(response['EnvironmentResources']['LoadBalancers'][0]['Name']))
responseData = {
"LBArn": lb_arn
}
cfnresponse.send(event,context,cfnresponse.SUCCESS,responseData)
else:
logger.info('Unexpected RequestType!')
cfnresponse.send(event,responseData)
except Exception as err:
logger.error(err)
responseData = {"Data": str(err)}
cfnresponse.send(event,cfnresponse.FAILED,responseData)
return
拥有您将要使用的资源:
"WAFAssociation": {
"Type" : "AWS::WAFv2::WebACLAssociation","Properties" : {
"ResourceArn" : { "GetAtt": ["MyCustomResource","LBArn"] },"WebACLArn" : { "Ref": "WAF" }
}
}