Blog

So können Sie Ihre cfn-guard Regeln testen

Joris Conijn

Joris Conijn

Aktualisiert Oktober 16, 2025
4 Minuten

In meinem letzten Blog, Wie beweisen Sie, dass Ihre Infrastruktur konform ist. habe ich erklärt, wie Sie die Konformität Ihrer Infrastruktur mit CloudFormation Guard beweisen können.

Aber wie schreiben Sie diese Regeln? Und was noch wichtiger ist, wie testen Sie Ihre Regeln? Wenn Sie sich das Repository CloudFormation Guard. ansehen, werden Sie feststellen, dass das Projekt selbst ein Test-Framework bietet.

Also gut! Lassen Sie uns einen Regelsatz erstellen und einige Tests dafür schreiben!

Lassen Sie uns einen Regelsatz für S3 erstellen

Wir beginnen mit einem Beispiel für S3 und erstellen eine Datei mit dem Namen: rules/s3.guard.

let buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]

rule BucketEncryption when %buckets !empty {
  %buckets.Properties {
    BucketEncryption.ServerSideEncryptionConfiguration[*] {
      ServerSideEncryptionByDefault.SSEAlgorithm IN ["AES-256", "aws:kms"] <<Ensure all S3 buckets use encryption-at-rest>>
    }
  }
}

Jetzt schreiben wir den Test mit dem Namen: rules/s3_tests.yaml.

---
- name: "Skip if not present"
  input:
     Resources: {}
  expectations:
    rules:
      BucketEncryption: SKIP
- name: "No encryption used"
  input:
     Resources:
       MyBucket:
         Type: AWS::S3::Bucket
  expectations:
    rules:
      BucketEncryption: FAIL

- name: "Bucket with KMS Encryption"
  input:
     Resources:
       MyBucket:
         Type: AWS::S3::Bucket
         Properties:
           BucketEncryption:
             ServerSideEncryptionConfiguration:
               - ServerSideEncryptionByDefault:
                   SSEAlgorithm: aws:kms
  expectations:
    rules:
      BucketEncryption: PASS

- name: "Bucket with AES-256 Encryption"
  input:
     Resources:
       MyBucket:
         Type: AWS::S3::Bucket
         Properties:
           BucketEncryption:
             ServerSideEncryptionConfiguration:
               - ServerSideEncryptionByDefault:
                   SSEAlgorithm: AES-256
  expectations:
    rules:
      BucketEncryption: PASS

- name: "Bucket with UNKNOWN Encryption"
  input:
     Resources:
       MyBucket:
         Type: AWS::S3::Bucket
         Properties:
           BucketEncryption:
             ServerSideEncryptionConfiguration:
               - ServerSideEncryptionByDefault:
                   SSEAlgorithm: UNKNOWN
  expectations:
    rules:
      BucketEncryption: FAIL

Jetzt ist es an der Zeit, die Tests durchzuführen:

cfn-guard test --rules-file rules/s3.guard --test-data rules/s3_tests.yaml

Dies ergibt die folgende Ausgabe:

Test Case #1
Name: "Skip if not present"
  PASS Rules:
    BucketEncryption: Expected = SKIP, Evaluated = SKIP

Test Case #2
Name: "No encryption used"
  PASS Rules:
    BucketEncryption: Expected = FAIL, Evaluated = FAIL

Test Case #3
Name: "Bucket with KMS Encryption"
  PASS Rules:
    BucketEncryption: Expected = PASS, Evaluated = PASS

Test Case #4
Name: "Bucket with AES-256 Encryption"
  PASS Rules:
    BucketEncryption: Expected = PASS, Evaluated = PASS

Test Case #5
Name: "Bucket with UNKNOWN Encryption"
  PASS Rules:
    BucketEncryption: Expected = FAIL, Evaluated = FAIL

Sie denken jetzt vielleicht: Das sieht doch gut aus! Aber die Ausgabe ist recht ausführlich, und Sie müssen für jede Regel/jeden Testsatz einen Befehl ausführen. Noch schlimmer wird es, wenn ein Test fehlschlägt. Für dieses Beispiel habe ich die Datei rules/s3.guard so geändert, dass aws:kmz anstelle von aws:kms verwendet wird. Dann sieht es so aus:

Test Case #1
Name: "Skip if not present"
  PASS Rules:
    BucketEncryption: Expected = SKIP, Evaluated = SKIP

Test Case #2
Name: "No encryption used"
  PASS Rules:
    BucketEncryption: Expected = FAIL, Evaluated = FAIL

Test Case #3
Name: "Bucket with KMS Encryption"
  FAILED Rules:
    BucketEncryption: Expected = PASS, Evaluated = FAIL

Test Case #4
Name: "Bucket with AES-256 Encryption"
  PASS Rules:
    BucketEncryption: Expected = PASS, Evaluated = PASS

Test Case #5
Name: "Bucket with UNKNOWN Encryption"
  PASS Rules:
    BucketEncryption: Expected = FAIL, Evaluated = FAIL

Wenn Sie sich Test Case #3 ansehen, steht dort: BucketEncryption: Expected = PASS, Evaluated = FAIL. Das macht es schwer zu erkennen, welcher Test fehlgeschlagen ist.

cfn-guard-test

Aus diesem Grund habe ich ein Python-Paket namens cfn-guard-test erstellt. Dieses Paket macht es einfacher, viele Regeln/Testsätze auszuführen. Dies ist besonders in den CI/CD-Pipelines nützlich.

Bitte lesen Sie die Installationsanweisungen im Repository.

Lassen Sie die Tests noch einmal laufen!

cfn-guard-test --verbose

Die Ausgabe sieht nun etwa so aus:

===== Analyzing Results =====

Running rules/s3_tests.yaml

Passed 5
Failed 0

Das ist eine schöne und saubere Übersicht. Sie listet die Anzahl der bestandenen und fehlgeschlagenen Tests auf. Für das nächste Beispiel änderte ich die rules/s3.guard Datei, um aws:kmz statt aws:kms zu verwenden. Dies führt erneut zu einem Fehler:

===== Analyzing Results =====

Running rules/s3_tests.yaml

Passed 4
Failed 1

Rule BucketEncryption failed on #3 "Bucket with KMS Encryption" in rules/s3.guard

Da müssen Sie zustimmen. Das fasst sofort zusammen, wie viele bestanden haben und wie viele durchgefallen sind. Und außerdem zeigt es, dass die BucketEncryption Regel schlägt fehl. Und bei dem Testfall "Bucket mit KMS-Verschlüsselung" schlägt sie fehl.

Sie möchten keine Zeit damit verbringen, herauszufinden, was falsch ist. Deshalb verwenden wir Werkzeuge, um uns das Leben leichter zu machen.

Mit diesem Tool können Sie auch einen JUnit-Bericht erstellen.

cfn-guard-test --verbose 
  --junit-path "reports/cfn-guard.xml"

Fazit

Mit cfn-guard-test können Sie viele Tests durchführen. Und Sie erhalten einen zusammengefassten Bericht mit den Ergebnissen. Dieses Tool wird Ihnen helfen, Fehler in Ihren Regeln einfacher und schneller zu finden.

Verfasst von

Joris Conijn

Joris is the AWS Practise CTO of the Xebia Cloud service line and has been working with the AWS cloud since 2009 and focussing on building event-driven architectures. While working with the cloud from (almost) the start, he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learning new things and experimenting with them because that is the way to learn and grow.

Contact

Let’s discuss how we can support your journey.