能否在AWS CloudFormation中使用非Base64字符串及S3文件作为输入?
当然可以!这个需求其实挺常见的,Base64确实不适合保留原始换行符这类格式,用S3存储文本再导入CloudFormation是非常可行的方案,我给你两种最常用的实现方式:
1. 直接用CloudFormation的Fn::GetContent函数(推荐)
这是CloudFormation提供的原生函数,专门用来读取S3对象的内容,能完美保留文本里的换行符、空格等格式。只要你的模板版本支持(目前大部分区域都支持),这是最简单的方法。
举个YAML模板的例子:
Parameters: TargetS3FileUrl: Type: String Description: S3 URL(比如`s3://my-bucket/path/to/my-text-file.txt`)指向带换行的文本文件 Resources: # 示例:用读取到的文本配置一个SNS主题的描述 MySNSTopic: Type: AWS::SNS::Topic Properties: DisplayName: "My Topic" TopicName: "MyTopic" # 直接把S3文件内容作为属性值,换行符会被完整保留 Description: !GetContent S3Url: !Ref TargetS3FileUrl
注意事项:
- 确保CloudFormation执行栈的角色(或者你手动创建栈用的IAM用户)有
s3:GetObject权限,目标S3对象的ACL或桶策略也要允许这个角色/用户访问。 Fn::GetContent支持直接用S3 URL,也可以分开指定Bucket和Key参数,比如:!GetContent Bucket: !Ref MyS3Bucket Key: !Ref MyS3Key
2. 自定义资源(Lambda)方案(兼容旧版本/复杂场景)
如果你的CloudFormation环境不支持Fn::GetContent(比如某些特殊区域或旧模板规范),可以用Lambda自定义资源来读取S3内容并返回给模板。这种方法更灵活,还能额外处理文本格式转换等逻辑。
示例模板片段:
Parameters: SourceS3Bucket: Type: String Description: 存储文本文件的S3桶名 SourceS3Key: Type: String Description: 文本文件在S3中的键路径 Resources: # 创建Lambda执行角色,赋予读取S3的权限 LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AllowS3Read PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: s3:GetObject Resource: !Sub arn:aws:s3:::${SourceS3Bucket}/${SourceS3Key} # 读取S3内容的Lambda函数 FetchS3ContentLambda: Type: AWS::Lambda::Function Properties: Runtime: python3.11 Handler: index.lambda_handler Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import json s3_client = boto3.client('s3') def lambda_handler(event, context): try: bucket = event['ResourceProperties']['SourceS3Bucket'] key = event['ResourceProperties']['SourceS3Key'] # 读取S3对象并转成UTF-8文本 response = s3_client.get_object(Bucket=bucket, Key=key) content = response['Body'].read().decode('utf-8') # 返回成功结果,把内容放在Data里 return { 'Status': 'SUCCESS', 'PhysicalResourceId': context.log_stream_name, 'Data': {'FileContent': content} } except Exception as e: return { 'Status': 'FAILED', 'PhysicalResourceId': context.log_stream_name, 'Reason': str(e) } # 调用自定义资源获取S3内容 S3ContentFetcher: Type: Custom::FetchS3Content Properties: ServiceToken: !GetAtt FetchS3ContentLambda.Arn SourceS3Bucket: !Ref SourceS3Bucket SourceS3Key: !Ref SourceS3Key # 输出读取到的内容,也可以直接在其他资源属性里引用 Outputs: ExtractedFileContent: Value: !GetAtt S3ContentFetcher.FileContent
总结
- 优先用
Fn::GetContent,原生支持,代码少,维护简单; - 自定义资源方案适合更复杂的场景,比如需要对文本做预处理,或者兼容旧环境;
- 无论哪种方法,核心都是确保CloudFormation拥有访问目标S3对象的权限,这是最容易踩坑的点。
内容的提问来源于stack exchange,提问作者Srinath Reddy
相关产品推荐
相关产品推荐

