2

我有一个自定义 CloudFormation 资源,如果它不存在,它会创建一个 S3 存储桶。这是代码:

  S3CustomResource:
Type: Custom::S3CustomResource
Properties:
  ServiceToken: !GetAtt AWSLambdaFunction.Arn
  the_bucket: !Ref S3BucketName

  AWSLambdaFunction:
 Type: "AWS::Lambda::Function"
 Properties:
   Description: "Work with S3 Buckets!"
   FunctionName: !Sub '${AWS::StackName}-${AWS::Region}-lambda'
   Handler: index.handler
   Role: !GetAtt AWSLambdaExecutionRole.Arn
   Timeout: 360
   Runtime: python3.6
   Code:
     ZipFile: |
      import boto3
      import cfnresponse
      def handler(event, context):
          # Init ...
          the_event = event['RequestType']
          print("The event is: ", str(the_event))
          response_data = {}
          s_3 = boto3.client('s3')
          # Retrieve parameters
          the_bucket = event['ResourceProperties']['the_bucket']
          try:
              if the_event in ('Create', 'Update'):
                  print("Requested to create S3 bucket: ", str(the_bucket))
                  for bucket_name in the_bucket:
                      print("Creating: ", str(bucket_name))
                      s_3.create_bucket(Bucket=the_bucket)
              elif the_event == 'Delete':
                  print("Whoopsie, this bucket has some seriuos information in it - let's not delete it")
              # Everything OK... send the signal back
              print("Execution succesfull!")
              cfnresponse.send(event,
                               context,
                               cfnresponse.SUCCESS,
                               response_data)
          except Exception as e:
              print("Execution failed...")
              print(str(e))
              response_data['Data'] = str(e)
              cfnresponse.send(event,
                               context,
                               cfnresponse.FAILED,
                               response_data)

我想在我的其他 CloudFormation 资源中引用此存储桶的 ARN。S3CustomResource 资源仅显示 CloudWatch 日志名称的 PhysicalID。如何让 CloudFormation 在“资源”选项卡中将存储桶 ARN 显示为 PhysicalID?

4

1 回答 1

1

存储桶 ARN 具有固定格式,因此您只需在代码中使用它(假设aws分区):

bucket_arn = "arn:aws:s3:::" + bucket_name

然后你把它们归还给response_data. 下面是完整工作的修改代码,可以使用自定义资源创建多个存储桶并将其 ARN 返回到 cloudformation 以供将来使用。代码有很大的改进空间,例如返回桶的arns(如果存在),检查桶是否被正确创建等等。因此它不是理想的代码,但它可以工作并显示关键元素:

  • 将列表传递给自定义资源
  • 将 arns 列表返回给 CFN
  • 访问 CFN 中的列表

Parameters:

  S3BucketName:
    Type: CommaDelimitedList  
    Default: test-bucket-312ddfff,test-bucket3333-312ddfff

Resources:

  S3CustomResource:
    Type: Custom::S3CustomResource
    Properties:
      ServiceToken: !GetAtt AWSLambdaFunction.Arn
      the_bucket: !Ref S3BucketName

  AWSLambdaFunction:
     Type: "AWS::Lambda::Function"
     Properties:
       Description: "Work with S3 Buckets!"
       FunctionName: !Sub '${AWS::StackName}-${AWS::Region}-lambda'
       Handler: index.handler
       Role: !GetAtt AWSLambdaExecutionRole.Arn
       Timeout: 360
       Runtime: python3.6
       Code:
         ZipFile: |
          import boto3
          import cfnresponse

          s_3 = boto3.client('s3')
          s3_waiter = s_3.get_waiter('bucket_exists')

          def handler(event, context):
              # Init ...
              
              print(event)

              the_event = event['RequestType']
              print("The event is: ", str(the_event))
              
              response_data = {}              

              # Retrieve parameters
              the_bucket = event['ResourceProperties']['the_bucket']
              
              print("the_bucket", the_bucket)
              
              bucket_arns = []

              try:
                  if the_event in ('Create', 'Update'):

                      print("Requested to create S3 bucket: ", 
                             str(the_bucket))

                      for bucket_name in the_bucket:
                      
                          print("Creating: ", str(bucket_name))
                          
                          s_3.create_bucket(Bucket=bucket_name)
                          
                          s3_waiter.wait(Bucket=bucket_name)
                          
                          bucket_arn = "arn:aws:s3:::" + bucket_name
                          
                          bucket_arns.append(bucket_arn)

                  elif the_event == 'Delete':
                      print("Whoopsie, this bucket has some"
                            "seriuos information in it "
                            "- let's not delete it")
                      cfnresponse.send(event, context,
                                       cfnresponse.SUCCESS,
                                       response_data)
                      return

                  # Everything OKindex... send the signal back

                  print("Execution successful!")
                  
                  response_data['arns'] = ','.join(bucket_arns)

                  cfnresponse.send(event,
                                   context,
                                   cfnresponse.SUCCESS,
                                   response_data)

              except Exception as e:

                  print("Execution failed...")
                  print(str(e))
                  
                  response_data['Data'] = str(e)

                  cfnresponse.send(event,
                                   context,
                                   cfnresponse.FAILED,
                                   response_data)
               
               
  AWSLambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'               
        Statement:
          - Effect: Allow
            Principal: {'Service': ['lambda.amazonaws.com']}
            Action: ['sts:AssumeRole']
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSLambdaExecute
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      Path: '/'
      
      
Outputs:

  BucketArns:
    Value: !GetAtt S3CustomResource.arns
于 2020-12-03T01:52:51.823 回答