如何使用 CloudFormation 创建 DocumentType 为 Package 的 'AWS::SSM::Document'

How to create an 'AWS::SSM::Document' with DocumentType of Package using CloudFormation

This AWS CloudFormation document 表明可以管理文档类型为 'Package' 的 'AWS::SSM::Document' 资源。然而,实现这一目标所需的 'Content' 仍然是个谜。

是否可以通过 CloudFormation 创建类型为 'Package' 的文档,如果可以,那么作为 CloudFormation 模板(最好使用 YAML 格式)编写的有效 CLI 命令的等价物是什么?

ssm create-document --name my-package --content "file://manifest.json" --attachments Key="SourceUrl",Values="s3://my-s3-bucket" --document-type Package

尝试失败。使用的内容是使用 CLI 选项时提供的 manifest.json 的内联版本。使用 CloudFormation 时似乎没有指定 AttachmentSource 的选项:

AWSTemplateFormatVersion: 2010-09-09

Resources:
  Document:
    Type: AWS::SSM::Document
    Properties:
      Name: 'my-package'
      Content: !Sub |
        {
          "schemaVersion": "2.0",
          "version": "Auto-Generated-1579701261956",
          "packages": {
            "windows": {
              "_any": {
                "x86_64": {
                  "file": "my-file.zip"
                }
              }
            }
          },
          "files": {
            "my-file.zip": {
              "checksums": {
                "sha256": "sha...."
              }
            }
          }
        }
      DocumentType: Package

CloudFormation 错误

AttachmentSource not provided in the input request. (Service: AmazonSSM; Status Code: 400; Error Code: InvalidParameterValueException;

似乎没有直接的方法可以通过 CloudFormation (CFN) 创建带附件的 SSM 文档。您可以使用一种解决方法,如使用支持的 Lambda CFN,您将使用 Lambda 调用 API SDK 来创建 SSM 文档,然后使用 CFN 中的自定义资源调用该 Lambda。

有关如何实施此解决方案的一些说明如下:

  • 如何从 CFN 调用 Lambda:
  • Lambda 发送响应格式示例(在 CFN 中使用自定义资源时):https://github.com/stelligent/cloudformation-custom-resources
  • 为了使用最佳实践部署 Lambda 并轻松上传附件,从本地文档内容,您应该使用 sam deploy 而不是 CFN create stack
  • 您可以通过将资源详细信息添加到 lambda 发回的响应中的 data json 来获取从 lambda 到 CFN 的新创建资源的信息,CFN 可以使用它! GetAtt CustomResrc.Attribute,您可以找到更多详细信息 here

此解决方案存在一些缺点:

  • 增加原始解决方案的复杂性,因为您必须为 Lambda 执行创建资源,例如(用于部署 Lambda 的 S3、用于 Lambda 执行的角色并承担 SSM 执行、SSM 内容文件 - 或者您必须使用'long' 内联内容)。它不再是 One-call CFN 创建堆栈。但是,您可以将所有内容都放入 SAM 模板中,因为归根结底,它只是一个 CFN 模板
  • 删除 CFN 堆栈时,您必须在 RequestType == Delete 时执行 lambda 以清理资源。

PS:如果你不必严格在 CFN 上工作,那么你可以尝试使用 Terraform:https://www.terraform.io/docs/providers/aws/r/ssm_document.html

是的,这是可能的!我已经使用 DocumentType: Package 成功创建了一个资源,在堆栈成功后,该包显示在 Distributor Packages 下的 SSM 控制台中。

你的 YAML 就差不多了,但你还需要包括 Attachments 属性 that is now available.

这是一个工作示例:

AWSTemplateFormatVersion: "2010-09-09"
Description: Sample to create a Package type Document

Parameters:
  S3BucketName:
    Type: "String"
    Default: "my-sample-bucket-for-package-files"
    Description: "The name of the S3 bucket."

Resources:
  CrowdStrikePackage:
    Type: AWS::SSM::Document
    Properties:
      Attachments:
        - Key: "SourceUrl"
          Values:
            - !Sub "s3://${S3BucketName}"
      Content:
        !Sub |
          {
              "schemaVersion": "2.0",
              "version": "1.0",
              "packages": {
                  "windows": {
                      "_any": {
                          "_any": {
                              "file": "YourZipFileName.zip"
                          }
                      }
                  }
              },
              "files": {
                  "YourZipFileName.zip": {
                      "checksums": {
                          "sha256": "7981B430E8E7C45FA1404FE6FDAB8C3A21BBCF60E8860E5668395FC427CE7070"
                      }
                  }
              }
          }
      DocumentFormat: "JSON"
      DocumentType: "Package"
      Name: "YourPackageNameGoesHere"
      TargetType: "/AWS::EC2::Instance"

注意:Attachments 属性 使用 DocumentType: Package 时必须使用 SourceUrl 键。创建过程将向此 S3 存储桶 URL 附加一个“/”,并将其与您在清单中列出的每个文件名连接起来,即创建程序包时的 Content 属性。