<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Janita Madramootoo - CGE-AUD</title>
      <link>https://janita.me</link>
      <description>Janita Madramootoo is a software architect in Melbourne, FL, writing about cloud infrastructure, security and compliance, and whatever else is worth taking apart.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://janita.me/tags/cge-aud/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Mon, 27 Jul 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Catching Up: Labs 2.5 - 4.3, and Passing the CGE-AUD Auditor Exam</title>
          <pubDate>Mon, 27 Jul 2026 00:00:00 +0000</pubDate>
          <author>Janita</author>
          <link>https://janita.me/blog/catching-up-on-lab-writeups-and-passing-cge-aud-exam/</link>
          <guid>https://janita.me/blog/catching-up-on-lab-writeups-and-passing-cge-aud-exam/</guid>
          <description xml:base="https://janita.me/blog/catching-up-on-lab-writeups-and-passing-cge-aud-exam/">&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;My last post left off at &lt;a href=&quot;https:&#x2F;&#x2F;janita.me&#x2F;blog&#x2F;terraform-compliant-gcp-storage-module&#x2F;&quot;&gt;Lab 2.4&lt;&#x2F;a&gt;. Since then, I&#x27;ve completed: Labs 2.5, 3.3, 3.4, and 4.3, plus the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grcengclub.com&#x2F;academy&#x2F;auditor&quot;&gt;GRC Auditor&lt;&#x2F;a&gt; exam. This is a quick summary with the main takeaway per lab.&lt;&#x2F;p&gt;
&lt;p&gt;Code for these labs is in my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JanitaM&#x2F;CGE-P_Capstone&quot;&gt;CGE-P Capstone repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grcengclub.com&#x2F;academy&#x2F;auditor&quot;&gt;GRC Auditor&lt;&#x2F;a&gt; exam was also launched in the meantime, recommended as a prerequisite to the CGE-P exam. My engineering background helped me knock it out in two days. Grateful for quick wins!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lab-2-5-iac-as-compliance-evidence-aws&quot;&gt;Lab 2.5: IaC as Compliance Evidence (AWS)&lt;&#x2F;h2&gt;
&lt;p&gt;This lab turns a Terraform plan into signed, retained evidence rather than just a deployment artifact. The module, &lt;code&gt;evidence-vault&lt;&#x2F;code&gt;, is an S3 bucket with Object Lock in GOVERNANCE mode. A capture script (&lt;code&gt;scripts&#x2F;capture-evidence.sh&lt;&#x2F;code&gt;) runs against a target workspace (in my case, &lt;a href=&quot;https:&#x2F;&#x2F;janita.me&#x2F;blog&#x2F;terraform-compliant-aws-s3-module-nist-800-53&#x2F;&quot;&gt;Lab 2.3&#x27;s &lt;code&gt;compliant-s3&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) and writes a receipt into the vault.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;What it proves&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Capture evidence against &lt;code&gt;compliant-s3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;The plan output itself becomes the evidence artifact&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Verify &lt;code&gt;RetainUntilDate&lt;&#x2F;code&gt; under GOVERNANCE mode&lt;&#x2F;td&gt;&lt;td&gt;Retention is enforced, not just configured&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Attempt &lt;code&gt;delete-object&lt;&#x2F;code&gt; on the locked object&lt;&#x2F;td&gt;&lt;td&gt;Confirms the lock actually blocks deletion with &lt;code&gt;AccessDenied&lt;&#x2F;code&gt; as expected&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;labs-3-3-3-4-writing-compliance-policies-in-rego-gcp-to-aws&quot;&gt;Labs 3.3 &amp;amp; 3.4: Writing Compliance Policies in Rego, GCP to AWS&lt;&#x2F;h2&gt;
&lt;p&gt;Lab 3.3 writes the policy library. Lab 3.4 proves it doesn&#x27;t have to be tied to one cloud provider.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lab-3-3-writing-compliance-policies-in-rego-gcp&quot;&gt;Lab 3.3: Writing Compliance Policies in Rego (GCP)&lt;&#x2F;h3&gt;
&lt;p&gt;Three Rego policies, three NIST controls, checked against a GCP Terraform plan:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Control&lt;&#x2F;th&gt;&lt;th&gt;File&lt;&#x2F;th&gt;&lt;th&gt;Enforces&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;SC-28&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;sc28_encryption.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Every &lt;code&gt;google_storage_bucket&lt;&#x2F;code&gt; has a populated &lt;code&gt;encryption { default_kms_key_name }&lt;&#x2F;code&gt; block&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AC-3&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ac3_no_public.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Buckets have &lt;code&gt;uniform_bucket_level_access = true&lt;&#x2F;code&gt; and &lt;code&gt;public_access_prevention = &quot;enforced&quot;&lt;&#x2F;code&gt;; firewalls don&#x27;t expose 22 or 3389 to &lt;code&gt;0.0.0.0&#x2F;0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CM-6&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;cm6_required_tags.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Every taggable resource carries the four required labels: &lt;code&gt;project&lt;&#x2F;code&gt;, &lt;code&gt;environment&lt;&#x2F;code&gt;, &lt;code&gt;managed_by&lt;&#x2F;code&gt;, &lt;code&gt;compliance_scope&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;lab-3-4-integrating-pac-with-terraform-via-conftest-aws&quot;&gt;Lab 3.4: Integrating PaC with Terraform via Conftest (AWS)&lt;&#x2F;h3&gt;
&lt;p&gt;This was my first exposure to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.conftest.dev&#x2F;&quot;&gt;Conftest&lt;&#x2F;a&gt;, Rego, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.openpolicyagent.org&#x2F;&quot;&gt;Open Policy Agent&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This lab does two things: runs the Lab 3.3 GCP policies against an AWS plan (they pass with zero coverage since there were no GCP resource types to check), and adds AWS-typed variants of the same three controls into the library. The point is that a control ID is portable across cloud providers while a Rego rule hardcoded to &lt;code&gt;google_storage_bucket&lt;&#x2F;code&gt; is not.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Control&lt;&#x2F;th&gt;&lt;th&gt;GCP file (3.3)&lt;&#x2F;th&gt;&lt;th&gt;AWS file (3.4)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;SC-28&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;sc28_encryption.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;sc28_encryption_aws.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AC-3&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ac3_no_public.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ac3_no_public_aws.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CM-6&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;cm6_required_tags.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;cm6_required_tags_aws.rego&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;lab-4-3-building-a-grc-evidence-pipeline-aws-github-actions&quot;&gt;Lab 4.3: Building a GRC Evidence Pipeline (AWS + GitHub Actions)&lt;&#x2F;h2&gt;
&lt;p&gt;Lab 4.3 wires the Lab 3.4 Conftest gate into GitHub Actions. Every PR now runs &lt;code&gt;terraform plan&lt;&#x2F;code&gt;, Conftest, and tfsec, and uploads a named evidence artifact regardless of pass or fail. The workflow file itself is the CM-3&#x2F;CM-6&#x2F;CA-2&#x2F;RA-5&#x2F;AU-9 audit evidence.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-iam-identity-center&quot;&gt;Setting up IAM Identity Center&lt;&#x2F;h3&gt;
&lt;p&gt;This was my first time setting up IAM Identity Center (SSO) on my personal AWS account. Up to this point, I&#x27;ve been working on the lab in CloudShell to avoid saving keys on my laptop. This has caused some headaches because AWS CloudShell only allows for 1 GB of persistent storage per AWS Region. I kept getting &quot;No space left on device&quot; errors on the AWS labs because every &lt;code&gt;terraform init&lt;&#x2F;code&gt; re-downloads its own full copy. Claude helped me find the Terraform plugin-cache and delete old files to make room for each new AWS lab, but it felt like I was just putting off the inevitable of setting up IAM Identity Center.&lt;&#x2F;p&gt;
&lt;p&gt;With OIDC, my sessions are short-lived and expire, which means occasionally re-authenticating, but nothing durable to leak and no forgetting about keys on my computer.&lt;&#x2F;p&gt;
&lt;p&gt;The guide&#x27;s reference &lt;code&gt;oidc&#x2F;main.tf&lt;&#x2F;code&gt; trusts the role to &lt;code&gt;repo:OWNER&#x2F;REPO:*&lt;&#x2F;code&gt;, so basically any branch, any event. In my repo, I tightened up both the subject claim and the permissions granted.&lt;&#x2F;p&gt;
&lt;p&gt;Since my repo has no remote backend configured, my state stays local. There&#x27;s no diff for testing drift against real infrastructure. The plan always shows a full &quot;create,&quot; not a diff against what&#x27;s actually live.&lt;&#x2F;p&gt;
&lt;p&gt;With identity and OIDC sorted, here&#x27;s the gate itself in action:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-two-pr-demonstration&quot;&gt;The two-PR demonstration&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Green&lt;&#x2F;strong&gt;: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JanitaM&#x2F;CGE-P_Capstone&#x2F;pull&#x2F;6&quot;&gt;PR #6&lt;&#x2F;a&gt;, merged. All checks passing.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Red&lt;&#x2F;strong&gt;: branch &lt;code&gt;lab-4-3-red&lt;&#x2F;code&gt;, opened, not merged. Conftest failed with:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[SC-28] aws_s3_bucket.primary: aws_s3_bucket has no matching aws_s3_bucket_server_side_encryption_configuration. Remediation: add one referencing this bucket.&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That message contains the control ID, resource, and remediation all in one line. The whole point of the gate is that this failure surfaces on the PR, before merge, instead of turning up as a finding in a later audit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;Takeaway&lt;&#x2F;h2&gt;
&lt;p&gt;Every gotcha I came across in these labs traced back to two things: my AWS CloudShell setup and that the guides are written for a flat, single-purpose repo. My repo has real structure, which means every path, working directory, and relative reference in the lab guides needed debugging (e.g. &lt;code&gt;TF_WORKING_DIR&lt;&#x2F;code&gt; pointed three levels deep so every &lt;code&gt;..&#x2F;&lt;&#x2F;code&gt; in the guide&#x27;s Conftest&#x2F;tfsec steps needed to become &lt;code&gt;..&#x2F;..&#x2F;..&#x2F;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
