You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从CloudFormation实例读取文件内容并在Outputs中展示

Hey there, let's break down why your current approach isn't working and walk through a solution to get that file content into your CloudFormation Outputs.

The Problem with Your Current Setup

CloudFormation's Fn::Sub and Fn::Join are template-level functions—they run when CloudFormation parses your template during deployment, not after your EC2 instance is up and running. So when you write !Sub "cat /opt/tmp/data", all CloudFormation does is output the string itself, not execute the command on the instance. The Outputs are finalized before your instance even has a chance to create or populate that /opt/tmp/data file.

The Solution: Combine User Data, SSM Parameter Store, and a Custom Resource

We need a way to:

  1. Get the EC2 instance to read the file and send its content to a place CloudFormation can access
  2. Fetch that content from CloudFormation and display it in Outputs

Here's a step-by-step implementation:

1. Configure EC2 Instance to Upload File Content to SSM

First, we'll give the EC2 instance permissions to write to AWS Systems Manager Parameter Store, then use User Data to upload the file content once it's available.

Resources:
  # IAM Role for EC2: Allows writing to SSM Parameter Store
  FileDataInstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: SSMPutParameterAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: ssm:PutParameter
                Resource: !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/cfn/instance-file-data'

  # Instance Profile to attach the role to EC2
  FileDataInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles: [!Ref FileDataInstanceRole]

  # Your EC2 Instance
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0c55b159cbfafe1f0 # Replace with your region's Amazon Linux 2 AMI
      InstanceType: t2.micro
      IamInstanceProfile: !Ref FileDataInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          # Wait for the /opt/tmp/data file to exist (adjust sleep time if needed)
          while [ ! -f /opt/tmp/data ]; do
            echo "Waiting for /opt/tmp/data to be created..."
            sleep 10
          done
          # Read the file content and upload to SSM Parameter Store
          FILE_CONTENT=$(cat /opt/tmp/data)
          aws ssm put-parameter --name "/cfn/instance-file-data" --type String --value "$FILE_CONTENT" --overwrite
          # Send success signal to CloudFormation to mark instance initialization as done
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyEC2Instance --region ${AWS::Region}
      # Wait for the instance to finish uploading the file before proceeding
      CreationPolicy:
        ResourceSignal:
          Timeout: PT15M # 15-minute timeout (adjust based on your file generation time)

2. Create a Lambda-Backed Custom Resource to Fetch the SSM Parameter

CloudFormation can't directly read SSM parameters into Outputs, so we'll use a Lambda function to pull the value and return it as a custom resource.

# IAM Role for Lambda: Allows reading SSM and interacting with CloudFormation
  FileDataLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: SSMGetParameterAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: ssm:GetParameter
                Resource: !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/cfn/instance-file-data'
        - PolicyName: LambdaBasicLogs
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: 'arn:aws:logs:*:*:*'

  # Lambda Function to read the SSM parameter
  FileDataLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.11
      Handler: index.lambda_handler
      Role: !GetAtt FileDataLambdaRole.Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse

          ssm_client = boto3.client('ssm')

          def lambda_handler(event, context):
              try:
                  # Only fetch the value on create/update events
                  if event['RequestType'] in ['Create', 'Update']:
                      param_response = ssm_client.get_parameter(
                          Name='/cfn/instance-file-data',
                          WithDecryption=False
                      )
                      file_content = param_response['Parameter']['Value']
                      # Send success response with the file content
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {'FileContent': file_content})
                  else:
                      # For delete events, just send success
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
              except Exception as e:
                  print(f"Error fetching parameter: {str(e)}")
                  cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})

  # Custom Resource to trigger the Lambda function
  FileDataCustomResource:
    Type: Custom::FileData
    Properties:
      ServiceToken: !GetAtt FileDataLambdaFunction.Arn
    DependsOn: MyEC2Instance # Ensure the instance has uploaded the file first

3. Add the File Content to Outputs

Finally, reference the custom resource's returned value in your Outputs:

Outputs:
  FileData:
    Description: "Content of /opt/tmp/data from the EC2 instance"
    Value: !GetAtt FileDataCustomResource.FileContent

Key Notes

  • Make sure your EC2 AMI has the AWS CLI installed (Amazon Linux 2 and Ubuntu Server images usually do by default)
  • Adjust the wait loop in User Data if your /opt/tmp/data file takes longer to generate
  • The CreationPolicy timeout should be long enough to cover your file generation and upload time
  • If your file has special characters (like newlines or quotes), you may need to escape them when uploading to SSM (e.g., using jq to format the content properly)

内容的提问来源于stack exchange,提问作者aihsts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:22:57