Blog

Die Verwendung von AWS CloudFormation-Makros ist ebenfalls schlicht und einfach

Martijn van Dongen

Aktualisiert Oktober 21, 2025
3 Minuten

Vor kurzem habe ich einen Blogbeitrag über die Erstellung einer benutzerdefinierten Ressource für AWS CloudFormation geschrieben, um eine zufällige Zeichenfolge zu erzeugen. Mit der Einführung der Makro-Unterstützung können wir sogar noch mehr tun. Ich habe eine ähnliche Funktion erstellt: einen Zufallsstring-Generator. Mit Hilfe von Makros generiert die Funktion jedes Mal, wenn Sie eine CloudFormation-Bereitstellung ausführen, eine neue Zeichenfolge.
Übrigens ist die Makro-Unterstützung zum Zeitpunkt der Veröffentlichung nur GA für ein paar Stunden. Ich wollte mit dieser neuen Funktion herumspielen und meine Erfahrungen schnell mit Ihnen teilen. Wahrscheinlich wird es bald eine Vielzahl von Anwendungsfällen geben. Wir hoffen, dass Sie mit diesem Blogbeitrag Ihr erstes Macro-Experiment in wenigen Minuten durchgeführt haben.

Einsetzen eines Macro Lambda

Zunächst müssen wir eine Lambda-Funktion bereitstellen. Natürlich mit den richtigen Richtlinien und Berechtigungen, und neu mit Macro müssen Sie eine AWS::CloudFormation::Transform Ressource hinzufügen.

AWSTemplateFormatVersion: 2010-09-09
Resources:
  TransformFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          import traceback
          import string
          import random

          def random_string(size=6):
            return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(size))

          def handler(event, context):
              response = {
                  "requestId": event["requestId"],
                  "status": "success"
              }
              params = event.get("params", {})
              operation = params.get("Operation", "upper")
              number = int(params.get("Number", 6))
              no_param_string_funcs = ["upper", "lower"]

              rs = random_string(number)
              if operation == "upper":
                  response["fragment"] = rs.upper()
              elif operation == "lower":
                  response["fragment"] = rs.lower()
              else:
                  response["status"] = "failure"

              return response

      Handler: index.handler
      Runtime: python3.6
      Role: !GetAtt TransformExecutionRole.Arn
  TransformExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: [lambda.amazonaws.com]
            Action: ['sts:AssumeRole']
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: ['logs:*']
                Resource: 'arn:aws:logs:*:*:*'
  TransformFunctionPermissions:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt TransformFunction.Arn
      Principal: "cloudformation.amazonaws.com"
  Transform:
    Type: AWS::CloudFormation::Transform
    Properties:
      Name: !Sub "${AWS::AccountId}::RandomString"
      content: "Generates a random string"
      RoutingTable:
        '*': 0_1
      Versions:
        - VersionName: 0_1
          content: "Version 0_1 of the RandomString Generator"
          FunctionName: !GetAtt TransformFunction.Arn
      ExecutionPolicy:
        Version: 2012-10-17
        Id: AllowOtherAccountPolicy
        Statement:
          - Sid: AllowExecution
            Effect: Allow
            Principal:
              AWS: !Sub '${AWS::AccountId}'
            Action: "cloudformation:CreateChangeSet"
            Resource: !Sub "arn:*:cloudformation:${AWS::Region}:${AWS::AccountId}:transform/RandomString"

Setzen Sie den Stack ein:

aws cloudformation deploy 
    --stack-name cfn-macro-randomstring 
    --template-file template.yaml 
    --capabilities CAPABILITY_IAM

Verwenden Sie das Makro

Jetzt können wir unser CloudFormation-Makro testen, indem wir die folgende Vorlage erstellen und bereitstellen. Wie ich schon sagte, wird bei jeder Bereitstellung eine neue zufällige Zeichenfolge erzeugt.

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: "join-test"
          Value: 
            'Fn::Join':
              - ''
              - - "mybucket-"
                - 'Fn::Transform':
                    Name: "RandomString"
                    Parameters:
                      Operation: "lower"
                      Number: "8"
aws cloudformation deploy 
    --stack-name test-the-macro 
    --template-file test.yaml

Die Makrofunktion ist einfach und bequem, wenn Sie wirklich jedes Mal, wenn Sie die Vorlage bereitstellen, etwas passieren soll. Es könnte praktisch sein, wenn Sie experimentieren und jedes Mal, wenn Sie etwas in Ihrem Stack ändern, eine neue Ressource, einen neuen Eigenschaftswert oder ein neues Attribut wünschen. Und natürlich können Sie sich noch viele weitere Anwendungsfälle vorstellen.
Ich habe versucht, die Kurzschreibweise !Sub zusammen mit !Transform { Name : RandomString } ohne Parameter zu verwenden, aber das wird noch nicht unterstützt. Obwohl die Dokumentationsseite sagt, dass es funktioniert. Könnte ein einfacher Fehler sein und schnell behoben werden.
Ich bin auch ein großer Fan von cfn-lint. Ich habe dies in meinem eigenen (eigenwilligen) cfn deployment cli automatisiert. Allerdings musste ich diese Prüfung jetzt deaktivieren, weil cfn-lint noch nicht aktuell ist. Und ich denke, dass es mit all den Möglichkeiten dieser Makrofunktion viel schwieriger wird, Richtlinien durchzusetzen.
Was mir an der neuen Makrofunktion gefällt, ist, dass die Lambda-Funktion sehr klein und einfach ist. Sie müssen nur ein paar Werte zurückgeben, anstatt einen speziellen CloudFormation-Endpunkt mit vielen Werten aufzurufen, wie es bei benutzerdefinierten Ressourcen erforderlich ist.
Wenn Sie Ihr eigenes Makro erstellen möchten, sehen Sie sich auch diese Beispiele an.

Verfasst von

Martijn van Dongen

Contact

Let’s discuss how we can support your journey.