<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dustin Whited</title>
    <description>The latest articles on Forem by Dustin Whited (@dgwhited).</description>
    <link>https://forem.com/dgwhited</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F840699%2F8c684b4e-05e3-4427-92be-6420822f5f86.jpeg</url>
      <title>Forem: Dustin Whited</title>
      <link>https://forem.com/dgwhited</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dgwhited"/>
    <language>en</language>
    <item>
      <title>Terraforming Resource Control Policies</title>
      <dc:creator>Dustin Whited</dc:creator>
      <pubDate>Mon, 18 Nov 2024 19:07:39 +0000</pubDate>
      <link>https://forem.com/aws-builders/terraforming-resource-control-policies-2bjg</link>
      <guid>https://forem.com/aws-builders/terraforming-resource-control-policies-2bjg</guid>
      <description>&lt;p&gt;AWS released a new type of organizational authorizational policy called Resource Control Policies (RCPs). This policy is considered a "resource-centric" policy, complementary to Service Control Policies "principal-centric" preventative guardrails.&lt;/p&gt;

&lt;p&gt;See the AWS release blog for more info about RCPs: &lt;a href="https://aws.amazon.com/blogs/aws/introducing-resource-control-policies-rcps-a-new-authorization-policy/" rel="noopener noreferrer"&gt;https://aws.amazon.com/blogs/aws/introducing-resource-control-policies-rcps-a-new-authorization-policy/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraforming
&lt;/h2&gt;

&lt;p&gt;One of the first questions I ask with a new AWS feature or service is "how do I automate it?" For RCPs, I asked a similar question and found that the AWS provider in Terraform had support as of &lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/40126" rel="noopener noreferrer"&gt;version 5.76.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, ensure you have the policy type enabled on your organization via "ALL" or "RESOURCE_CONTROL_POLICY" like shown below. This will enable RCPs as well as attach RCPFullAWSAccess.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_organizations_organization"&lt;/span&gt; &lt;span class="s2"&gt;"org"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;feature_set&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ALL"&lt;/span&gt;
  &lt;span class="nx"&gt;enabled_policy_types&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"AISERVICES_OPT_OUT_POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"SERVICE_CONTROL_POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"RESOURCE_CONTROL_POLICY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure your provider is up to 5.76. You could also use "~&amp;gt; 5.0". &lt;/p&gt;

&lt;p&gt;See Version Constraints documentation for more info on how this works &lt;a href="https://developer.hashicorp.com/terraform/language/expressions/version-constraints" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/expressions/version-constraints&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;
&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.76"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can create a RCP. I'm using the &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html" rel="noopener noreferrer"&gt;confused deputy&lt;/a&gt; prevention example provided from &lt;a href="https://github.com/aws-samples/data-perimeter-policy-examples" rel="noopener noreferrer"&gt;aws-samples&lt;/a&gt;. Note that RCPs have similar limits to SCPs. You can only attach 5 per entity (OU and account), RCPFullAWSAccess counts against the limit, and they have a character limit of 5120 that includes whitespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"rcp1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Deny"&lt;/span&gt;

    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"s3:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"sqs:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"kms:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"secretsmanager:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"sts:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="nx"&gt;identifiers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringNotEqualsIfExists"&lt;/span&gt;
      &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws:SourceOrgID"&lt;/span&gt;

      &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;aws_organizations_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Null"&lt;/span&gt;
      &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws:SourceAccount"&lt;/span&gt;

      &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"false"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bool"&lt;/span&gt;
      &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws:PrincipalIsAWSService"&lt;/span&gt;

      &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"true"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_organizations_policy"&lt;/span&gt; &lt;span class="s2"&gt;"rcp1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rcp1"&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rcp1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"RESOURCE_CONTROL_POLICY"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are combining multiple RCPs into a single &lt;code&gt;aws_iam_policy_document&lt;/code&gt;, you may want to use &lt;code&gt;minified_json&lt;/code&gt; instead of &lt;code&gt;json&lt;/code&gt; on the content argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_organizations_policy"&lt;/span&gt; &lt;span class="s2"&gt;"rcp1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rcp1"&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rcp1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minified_json&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"RESOURCE_CONTROL_POLICY"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, attach it to an entity. In this case, I am attaching it to an OU I have called "dev" under the organization root.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_organizations_organizational_unit"&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
  &lt;span class="nx"&gt;parent_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_organizations_organization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;org&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roots&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_organizations_policy_attachment"&lt;/span&gt; &lt;span class="s2"&gt;"rcp1_dev"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;policy_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_organizations_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rcp1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;target_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_organizations_organizational_unit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's very nice to see Terraform provider support so quickly for a new release, especially on governance features.&lt;/p&gt;

&lt;p&gt;Happy RCP'ing!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Introducing Amazon GuardDuty Detector Checker: Verify Enablement and Finding Publishing Configurations</title>
      <dc:creator>Dustin Whited</dc:creator>
      <pubDate>Tue, 22 Oct 2024 17:33:47 +0000</pubDate>
      <link>https://forem.com/dgwhited/introducing-amazon-guardduty-detector-checker-verify-enablement-and-finding-publishing-configurations-47dj</link>
      <guid>https://forem.com/dgwhited/introducing-amazon-guardduty-detector-checker-verify-enablement-and-finding-publishing-configurations-47dj</guid>
      <description>&lt;p&gt;I am excited to release my latest open-source project: &lt;a href="https://github.com/dgwhited/guardduty-detector-check" rel="noopener noreferrer"&gt;Amazon GuardDuty Detector Checker&lt;/a&gt;. This Python-based tool addresses the challenge of validating the configuration of Amazon GuardDuty across multiple regions in your AWS environment. It can also aid in gathering information to import GuardDuty resources to Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Manually checking each region for GuardDuty status, detector IDs, and publishing destinations is time-consuming and prone to oversight. Importing this all to Terraform helps wrangle GuardDuty as well as allow organizations to quickly roll out new features, such as the recently released malware protection for S3 &lt;a href="https://aws.amazon.com/blogs/aws/introducing-amazon-guardduty-malware-protection-for-amazon-s3/" rel="noopener noreferrer"&gt;https://aws.amazon.com/blogs/aws/introducing-amazon-guardduty-malware-protection-for-amazon-s3/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Amazon GuardDuty Detector Checker Helps
&lt;/h2&gt;

&lt;p&gt;Our tool simplifies this process by automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Listing all enabled regions in your AWS account&lt;/li&gt;
&lt;li&gt;Checking GuardDuty status in each enabled region&lt;/li&gt;
&lt;li&gt;Retrieving GuardDuty detector IDs where available&lt;/li&gt;
&lt;li&gt;Fetching publishing destinations and IDs for enabled detectors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This overview allows security teams to quickly identify gaps in GuardDuty coverage and ensure proper configuration across all regions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Tool
&lt;/h2&gt;

&lt;p&gt;The Amazon GuardDuty Detector Checker is easy to use and requires minimal setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install via PyPi with pip

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pip install guardduty-detector-checker&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the script with an optional AWS profile name

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;guardduty-detector-checker [-p PROFILE]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tool outputs a JSON-formatted list of GuardDuty status across all enabled regions in the AWS account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"abc123ABC123abc123ABC123abc123AB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"DestinationId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abcABCdefDEFghiGHIjklJKLmnoMNO12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"DestinationType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"S3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUBLISHING"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"us-west-2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These IDs can then be used in Terraform import blocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_guardduty_detector"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;enable&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;finding_publishing_frequency&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"FIFTEEN MINUTES"&lt;/span&gt;
  &lt;span class="nx"&gt;datasources&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;audit_logs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enable_kubernetes_audit_logs&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;malware_protection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;scan_ec2_instance_with_findings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ebs_volumes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enable_malware_protection&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;s3_logs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enable_s3_logs&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_guardduty_detector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"abc123ABC123abc123ABC123abc123AB"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_guardduty_publishing_destination"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;detector_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_guardduty_detector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;destination_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_bucket&lt;/span&gt;
  &lt;span class="nx"&gt;kms_key_arn&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_kms_key&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_guardduty_publishing_destination&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"abc123ABC123abc123ABC123abc123AB:abcABCdefDEFghiGHIjklJKLmnoMNO12"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Amazon GuardDuty Detector Checker is available on my &lt;a href="https://github.com/dgwhited/guardduty-detector-check" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, where you can find documentation, contribute to the project, or adapt it to your specific needs.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscommunitybuilder</category>
      <category>security</category>
      <category>terraform</category>
    </item>
    <item>
      <title>The Importance of Internal Cloud Security Standards</title>
      <dc:creator>Dustin Whited</dc:creator>
      <pubDate>Wed, 21 Dec 2022 18:51:04 +0000</pubDate>
      <link>https://forem.com/aws-builders/the-importance-of-internal-cloud-security-standards-5en4</link>
      <guid>https://forem.com/aws-builders/the-importance-of-internal-cloud-security-standards-5en4</guid>
      <description>&lt;h2&gt;
  
  
  Why You Need an Internal Standard
&lt;/h2&gt;

&lt;p&gt;Internal standards contain prescriptive statements that provide engineers with a recipe to create repeatable secure processes. These statements declare how infrastructure or processes should be defined and are a baseline for security in a cloud environment. &lt;/p&gt;

&lt;p&gt;Standards can also be written into reusable modules. When owned and maintained centrally, these modules provide developers with preconfigured templates that adhere to security standards. Converting the standard into &lt;a href="https://docs.hashicorp.com/sentinel/concepts/policy-as-code" rel="noopener noreferrer"&gt;policy as code&lt;/a&gt; allows immediate feedback to developers, linting the code as they are writing it. This allows developers to create business value quicker while reducing the amount of security remediation needed after deployment. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to Write a Standard
&lt;/h2&gt;

&lt;p&gt;Just like the standards themselves, how it is written will depend upon the needs of the organization. There are a few overall commonalities, however.&lt;/p&gt;

&lt;p&gt;A standard should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be &lt;a href="https://datatracker.ietf.org/doc/html/rfc2119" rel="noopener noreferrer"&gt;RFC2119&lt;/a&gt; compliant. This means using words like MUST, and SHOULD to indicate requirements.&lt;/li&gt;
&lt;li&gt;Be &lt;a href="https://datatracker.ietf.org/doc/html/rfc8174" rel="noopener noreferrer"&gt;RFC8174&lt;/a&gt; compliant. An add-on to the previous RFC, it specifies the required keywords’ capitalization.&lt;/li&gt;
&lt;li&gt;Be precise when prescribing the requirements.

&lt;ul&gt;
&lt;li&gt;“S3 buckets MUST use SSE-S3 or SSE-KMS encryption keys.”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Have different requirements for applications with different risk levels and criticality.

&lt;ul&gt;
&lt;li&gt;Requiring the use of CloudHSM for a moderate risk workload is not a realistic view of the threats.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Have a key for each requirement that can be referred to by external systems. This is particularly important for organizations that use multiple cloud service providers (CSPs), as it helps to ensure the appropriate control is applied to the correct environment.

&lt;ul&gt;
&lt;li&gt;AWS.IAM.1 - Identity and Access Management (IAM) users MUST NOT exist.&lt;/li&gt;
&lt;li&gt;GCP.GCE.1 - Identity Aware Proxy (IAP) MUST be used for all human remote connections to virtual machines.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Choose an accessible location to host the standard. This could be Confluence, a Google doc, or Github. Writing the standard should be a collaborative effort that includes the business owner, engineering, and security to ensure the requirements are realistic and align with the business’s risk appetite.&lt;/p&gt;

&lt;p&gt;One size does not fit all in large complex environments. Many of the standards and benchmarks are written so that they can apply to a variety of environments. Take for example the CIS Benchmark for Amazon Web Services (AWS). There is a &lt;a href="https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls-1.4.0.html#securityhub-cis1.4-controls-3.4" rel="noopener noreferrer"&gt;control for integrating CloudTrail with CloudWatch&lt;/a&gt; logs so that metric filters for alerts can be created. This control is irrelevant in an environment that has a security information and event management (SIEM) or other log aggregation and alerting tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement a Standard
&lt;/h2&gt;

&lt;p&gt;Once an internal cloud security standard has been written, the next step is to implement and enforce its requirements. Requiring 30 new standards at once would create a large burden upon development teams to triage and remediate, pulling attention away from building business features. Enablement should be a planned and methodical process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Roadmap
&lt;/h3&gt;

&lt;p&gt;Create a roadmap for enabling the controls. If there are any low effort, high impact items, prioritize those first. Often these are related to any publicly available resources to reduce and secure the attack surface. Some controls may have hidden complexity that is revealed by talking to the developer of the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find the Baseline
&lt;/h3&gt;

&lt;p&gt;The first step is to create detective capabilities to monitor compliance with the new control. In AWS Config is frequently used in tandem with Security Hub, but there is a large variety of Cloud Security Posture Management (CSPM) tools on the market that operate across multiple CSPs. This will not only provide a mechanism to detect compliance, but also give a general idea of the remediation work that needs to be done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Facilitate Developer Enablement
&lt;/h3&gt;

&lt;p&gt;The next step is to provide the development teams with the baselines and a target enforcement date. The standard should include documentation on how to implement the controls, and there should be a mechanism to provide feedback to the development teams as they are working on implementing the standards. This could be in the form of linting the code as it is written, developing preconfigured secure modules, or providing training for the engineering teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Standards as Code
&lt;/h3&gt;

&lt;p&gt;During the baseline phase, detective capabilities were created to detect compliance to controls. Because we do not want development teams to be in a constant state of remediation, for every detective capability, there should also be a preventative capability.&lt;/p&gt;

&lt;p&gt;This preventative capability can be written as code, using policy as code tools such as Snyk, Terrascan, and OPA. Once the rules are written, they can be added to git repos as a pre-merge check. This creates a consistently applied process that is easy to maintain and audit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Internal cloud security standards are essential for ensuring secure processes and reducing the amount of security remediation needed after deployment. Standards should be written in a precise and RFC-compliant manner and should be tailored to the risk appetite of the organization. Implementation should be done in a methodical way, with detective and preventative capabilities written as code and shared with development teams.&lt;/p&gt;

</description>
      <category>indonesia</category>
    </item>
    <item>
      <title>Threat Detection on EKS – Comparing Falco and GuardDuty For EKS Protection</title>
      <dc:creator>Dustin Whited</dc:creator>
      <pubDate>Fri, 06 May 2022 19:40:01 +0000</pubDate>
      <link>https://forem.com/aws-builders/threat-detection-on-eks-comparing-falco-and-guardduty-for-eks-protection-2m6b</link>
      <guid>https://forem.com/aws-builders/threat-detection-on-eks-comparing-falco-and-guardduty-for-eks-protection-2m6b</guid>
      <description>&lt;p&gt;&lt;em&gt;Co-authored by &lt;a href="https://www.linkedin.com/in/dustinwhited/" rel="noopener noreferrer"&gt;Dustin Whited&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/dakota-riley-b48401b7" rel="noopener noreferrer"&gt;Dakota Riley&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes adoption has grown, with managed services leading implementation according to a recent &lt;a href="https://www.cncf.io/reports/cncf-annual-survey-2021/" rel="noopener noreferrer"&gt;Cloud Native Computing Foundation (CNCF) survey&lt;/a&gt;. "79% of respondents use Certified Kubernetes Hosted platforms" with Amazon’s managed Kubernetes offering, Elastic Kubernetes Service (EKS), being the most popular of the hosted platforms.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aws.github.io/aws-eks-best-practices/security/docs/#understanding-the-shared-responsibility-model" rel="noopener noreferrer"&gt;shared responsibility model&lt;/a&gt; means the customer is responsible for securing the workloads running on EKS. In January, 2022, AWS &lt;a href="https://aws.amazon.com/about-aws/whats-new/2022/01/amazon-guardduty-elastic-kubernetes-service-clusters/" rel="noopener noreferrer"&gt;released new functionality for GuardDuty&lt;/a&gt; enabling threat detection on EKS clusters and aiding customers with securing their workloads. This new capability uses the Kubernetes Audit log to monitor for suspicious or malicious activity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://falco.org/" rel="noopener noreferrer"&gt;Falco&lt;/a&gt;, a CNCF project, is a common open source tool used to perform similar threat detection capabilities within Kubernetes clusters. Falco monitors system calls from the Linux kernel for the majority of its analysis. It is also preloaded with community maintained rule sets.&lt;/p&gt;

&lt;p&gt;This blog will explore some commonalities and differences between Falco and the new GuardDuty feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ease of implementation
&lt;/h2&gt;

&lt;p&gt;GuardDuty Kubernetes protection is not enabled by default. Accounts that are in an AWS Organization can enable the feature through the &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html#k8s-multiaccount" rel="noopener noreferrer"&gt;GuardDuty delegated administrator&lt;/a&gt; account, or the &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/kubernetes-protection.html#data-source-configure" rel="noopener noreferrer"&gt;detector can be updated&lt;/a&gt; on an individual account. Terraform support is &lt;a href="https://github.com/hashicorp/terraform-provider-aws/pull/22859" rel="noopener noreferrer"&gt;pending&lt;/a&gt; at the time of writing, while &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-guardduty-detector-cfnkubernetesconfiguration.html" rel="noopener noreferrer"&gt;Cloudformation&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_guardduty.CfnDetector.CFNKubernetesConfigurationProperty.html" rel="noopener noreferrer"&gt;CDK&lt;/a&gt; support is fully implemented.&lt;/p&gt;

&lt;p&gt;It is also worth noting that enabling EKS GuardDuty incurs &lt;a href="https://aws.amazon.com/guardduty/pricing/" rel="noopener noreferrer"&gt;additional pricing&lt;/a&gt; per one million audit events ingested. The cost is reasonable, but environments with many clusters or a high amount of activity may incur a surprise billing statement after the 30 day trial ends.&lt;/p&gt;

&lt;p&gt;Falco can be installed with a &lt;a href="https://falco.org/docs/getting-started/deployment/" rel="noopener noreferrer"&gt;chart&lt;/a&gt; as a &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/" rel="noopener noreferrer"&gt;daemonset&lt;/a&gt; in the cluster, or directly &lt;a href="https://falco.org/docs/getting-started/installation/" rel="noopener noreferrer"&gt;installed on the host &lt;/a&gt;operating system. Installing as a daemonset is the simplest way to get started with Falco, however installing on the OS insulates it from Kubernetes itself. Organizations that create hardened custom node AMIs may find it easiest to include Falco through the image build process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding types
&lt;/h2&gt;

&lt;p&gt;At a high level, EKS GuardDuty is ultimately more focused on detecting malicious activity against the EKS Control Plane, whereas by default Falco is better suited to detecting malicious activity on a container running on the cluster, or the host itself. &lt;/p&gt;

&lt;p&gt;While there is some overlap in rules, GuardDuty and Falco detections are not congruent. At the time of writing, GuardDuty has 27 Kubernetes findings that leverage the &lt;a href="https://kubernetes.io/docs/tasks/debug-application-cluster/audit/" rel="noopener noreferrer"&gt;Kubernetes Audit &lt;/a&gt;log. Importantly, regular GuardDuty findings for EC2 will also apply to the Kubernetes nodes. With over 68 community rules, Falco monitors syscalls from the Linux kernel by default and optionally can consume the Kubernetes Audit log - this requires configuring additional logic with a CloudWatch subscription filter on the EKS Audit Logs CloudWatch to feed it back into Falco.&lt;/p&gt;

&lt;p&gt;Below we compare and contrast some notable detection capabilities of the two tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anonymous Access:
&lt;/h3&gt;

&lt;p&gt;EKS can be configured to allow anonymous access to its control plane (relevant GitHub Issue on AWS Containers Roadmap &lt;a href="https://github.com/aws/containers-roadmap/issues/532" rel="noopener noreferrer"&gt;here&lt;/a&gt;). This configuration should almost never exist. This is an excellent "low-hanging fruit" detection provided by EKS GuardDuty upon that access being configured:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#policy-kubernetes-anonymousaccessgranted" rel="noopener noreferrer"&gt;Policy:Kubernetes/AnonymousAccessGranted&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is also worth noting that EKS GuardDuty also includes findings for actual usage of that anonymous access - which can help inform your response, the findings themselves are categorized based on the specific APIs (which are not publicized by AWS) being called anonymously: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#credentialaccess-kubernetes-successfulanonymousaccess" rel="noopener noreferrer"&gt;CredentialAccess:Kubernetes/SuccessfulAnonymousAccess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#defenseevasion-kubernetes-successfulanonymousaccess" rel="noopener noreferrer"&gt;DefenseEvasion:Kubernetes/SuccessfulAnonymousAccess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#discovery-kubernetes-successfulanonymousaccess" rel="noopener noreferrer"&gt;Discovery:Kubernetes/SuccessfulAnonymousAccess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#impact-kubernetes-successfulanonymousaccess" rel="noopener noreferrer"&gt;Impact:Kubernetes/SuccessfulAnonymousAccess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#persistence-kubernetes-successfulanonymousaccess" rel="noopener noreferrer"&gt;Persistence:Kubernetes/SuccessfulAnonymousAccess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Falco also has an anonymous access rule in its K8s Audit Logs ruleset, but requires the additional logic to feed into the engine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/falcosecurity/falco/blob/f86423db76ce79917ae30499e17726e942a678b6/rules/k8s_audit_rules.yaml#L207-L215" rel="noopener noreferrer"&gt;Falco anonymous access rule&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Syscalls and Malicious Runtime Activity:
&lt;/h3&gt;

&lt;p&gt;Where Falco shines is its ability to ingest syscalls from containers on the cluster to detect malicious activity on the container itself. EKS GuardDuty currently only alerts on activities against the K8s Control Plane of the cluster. Highlighting a few default Falco rules below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/falcosecurity/falco/blob/eae193ade074b5e18541526928ada845e1b31036/rules/falco_rules.yaml#L2348" rel="noopener noreferrer"&gt;Contact EC2 Instance Metadata Service From Container - &lt;/a&gt;Specific to AWS - this finding indicates when a container makes a call to the &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html" rel="noopener noreferrer"&gt;IMDS&lt;/a&gt; endpoint, which would by default provide access to credentials for the EKS Node Instance Role. In most cases, this would be an indicator of lateral movement/recon attempts on a compromised container (see also: &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html" rel="noopener noreferrer"&gt;IAM Roles for Service Accounts&lt;/a&gt; and &lt;a href="https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node" rel="noopener noreferrer"&gt;Restrict Access to the Node Instance Profile&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/falcosecurity/falco/blob/eae193ade074b5e18541526928ada845e1b31036/rules/falco_rules.yaml#L2402" rel="noopener noreferrer"&gt;Contact K8s API Server From Container&lt;/a&gt; - This finding can be an indicator of lateral movement/recon attempts on a compromised container. Allowlisting legitimate access by management tools may be required in order to be a high fidelity alert.&lt;/p&gt;

&lt;h3&gt;
  
  
  Known Malicious IP:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#defenseevasion-kubernetes-maliciousipcaller" rel="noopener noreferrer"&gt;GuardDuty supports Malicious IP Caller detection&lt;/a&gt; which will alert on malicious IP addresses invoking Kubernetes API calls. Similar to the Anonymous Access findings, EKS GuardDuty has a number of Malicious IP Caller finding types that will trigger based on the Kubernetes API being called. For example, &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#discovery-kubernetes-maliciousipcaller" rel="noopener noreferrer"&gt;Discovery:Kubernetes/MaliciousIPCaller&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-kubernetes.html#impact-kubernetes-maliciousipcaller" rel="noopener noreferrer"&gt;Impact:Kubernetes/MaliciousIPCaller&lt;/a&gt; both trigger on malicious IPs, but are dependent on the specific API being called. &lt;/p&gt;

&lt;p&gt;Falco requires a static deny list of malicious IPs or domain names, which is not optimal to maintain up to date threat intelligence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cryptomining:
&lt;/h3&gt;

&lt;p&gt;While not part of EKS GuardDuty specifically, the EC2 finding &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-ec2.html#cryptocurrency-ec2-bitcointoolbdns" rel="noopener noreferrer"&gt;CryptoCurrency:EC2/BitcoinTool.B!DNS&lt;/a&gt; will alert on resources within the cluster contacting Crypto Mining domains. GuardDuty is automatically updated with the latest threat intel feeds from &lt;a href="https://aws.amazon.com/guardduty/resources/partners/" rel="noopener noreferrer"&gt;Crowdstrike and ProofPoint&lt;/a&gt; so it will always have up to date information. &lt;/p&gt;

&lt;p&gt;Falco has a rule to detect &lt;a href="https://github.com/falcosecurity/falco/blob/f86423db76ce79917ae30499e17726e942a678b6/rules/falco_rules.yaml#L2724" rel="noopener noreferrer"&gt;crypto miner domains&lt;/a&gt; but it is not enabled because Falco will invoke a DNS lookup to determine if it is in the list, which may trigger alerts external to Falco. This list is also not a true threat intel feed. One advantage to using Falco for this use case is that it will provide helpful metadata about the container in question making the calls to cryptoming domains, where GuardDuty will only provide the EC2 Instance and associated IP addresses and require additional enrichment to triage further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizability
&lt;/h2&gt;

&lt;p&gt;Customization can be a game changer for threat detection tooling, especially when it comes to fine tuning the fidelity of the findings. On the other hand, not all teams have the bandwidth to tune findings or implement custom detections. A look below at the customization ability of both tools:&lt;/p&gt;

&lt;p&gt;GuardDuty findings cannot be customized. Some post-processing of the finding is possible with external integrations like Lambda – for example to reduce the severity level of the finding. While findings are not able to be customized, GuardDuty supports importing both custom threat lists or trusted IP lists, as well as native &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/findings_suppression-rule.html" rel="noopener noreferrer"&gt;suppression rule&lt;/a&gt; capabilities. &lt;/p&gt;

&lt;p&gt;Existing Falco rules can be disabled or modified. New supplemental rules can be written to detect environment specific use cases. Falco is not just limited to Kubernetes syscalls or audit logs - recently Falco released a &lt;a href="https://falco.org/docs/plugins/developers-guide/" rel="noopener noreferrer"&gt;plugin capability&lt;/a&gt;, allowing Falco to be extended to consume additional event sources. One such example of this is the &lt;a href="https://github.com/falcosecurity/plugins/tree/master/plugins/cloudtrail" rel="noopener noreferrer"&gt;AWS CloudTrail Plugin&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrations
&lt;/h2&gt;

&lt;p&gt;Alerts need to have an action or notification method to bring value to a security organization. Integrating GuardDuty and Falco with external systems to notify a responder or take action is achieved in a couple different ways.&lt;/p&gt;

&lt;p&gt;GuardDuty findings are sent to AWS services like SecurityHub and the default Eventbridge eventbus within the administrator account. Both allow consumption into a SIEM of choice, direct alerting with Chatbot, or even taking action with a Step Function workflow. For an example of auto-remediation using a Step Function workflow see our &lt;a href="https://blog.aquia.us/blog/2022-03-11-auto-remediation-with-eventbridge-step-functions/" rel="noopener noreferrer"&gt;previous blog&lt;/a&gt; on this topic.&lt;/p&gt;

&lt;p&gt;Falco can &lt;a href="https://falco.org/docs/alerts/" rel="noopener noreferrer"&gt;emit its findings&lt;/a&gt; to stdout, a file, syslog, or custom endpoints with "Program Output" using bash. Alternatively, &lt;a href="https://github.com/falcosecurity/falcosidekick" rel="noopener noreferrer"&gt;Falcosidekick&lt;/a&gt; is an extra app that receives Falco alerts from multiple clusters and forwards them to a variety of outputs concurrently. Falcosidekick has a large number of custom destinations, so it may reduce the need to write custom integrations for existing destinations like a SIEM.&lt;/p&gt;

&lt;p&gt;Overall, both GuardDuty and Falco will require some level of investment into integrating the alerts with existing systems. The only exception is if SecurityHub is the primary location as GuardDuty sends findings there by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;GuardDuty EKS protection offers very quick centralized enablement and is managed by AWS for updates to findings. Enabling this functionality is a new best practice and should be enabled organization-wide as it only costs money when an EKS cluster is present and has activity.&lt;/p&gt;

&lt;p&gt;Falco offers an increased level of customization and granularity that GuardDuty does not. Falco should be enabled in organizations with the maturity to tune and monitor the alerts, as well as create defined runbooks for responders.&lt;/p&gt;

&lt;p&gt;In the end, it is not usually an either-or situation for GuardDuty EKS and Falco, but rather each is a milestone on a maturity roadmap. The two tools complement each other to supplement a defense in depth strategy securing container workloads on AWS.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The information presented was current as of date of publication 05/06/2022&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>security</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Auto Remediation with Eventbridge, Step Functions, and the AWS SDK Integration</title>
      <dc:creator>Dustin Whited</dc:creator>
      <pubDate>Fri, 01 Apr 2022 18:55:55 +0000</pubDate>
      <link>https://forem.com/aws-builders/auto-remediation-with-eventbridge-step-functions-and-the-aws-sdk-integration-5bao</link>
      <guid>https://forem.com/aws-builders/auto-remediation-with-eventbridge-step-functions-and-the-aws-sdk-integration-5bao</guid>
      <description>&lt;p&gt;In late 2021, AWS released a new feature for Step Functions (SFN) &lt;a href="https://aws.amazon.com/about-aws/whats-new/2021/09/aws-step-functions-200-aws-sdk-integration/" rel="noopener noreferrer"&gt;allowing AWS SDK calls directly from the workflow&lt;/a&gt;. Previously, a Lambda function or &lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-ssm-docs.html" rel="noopener noreferrer"&gt;SSM document&lt;/a&gt; would be invoked by the SFN State Machine to make AWS SDK calls. This new feature allows low to no code workflows within AWS.&lt;/p&gt;

&lt;p&gt;This is important because unmaintained code may introduce vulnerabilities into the environment and create tech debt. Ultimately, the responsibility for keeping code up to date in a cloud environment lies squarely with the customer. This new Step Functions SDK integration reduces the operational burden on security teams by transferring that responsibility to the Cloud Service Provider. This blog will explore an example of functionless auto remediation of a public resource exposure using the SFN SDK integration and Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case: EBS Snapshot Made Public
&lt;/h2&gt;

&lt;p&gt;All write events that are recorded by CloudTrail are also sent to the Default EventBridge Event bus. Read-only events are not currently sent to the default event bus and cannot trigger a workflow. Modifying a snapshot results in a write CloudTrail event, making this remediation workflow possible.&lt;/p&gt;

&lt;p&gt;Modifying a snapshot to be public results in the following sample CloudTrail event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"00000000-0000-0000-0000-000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detail-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWS API Call via CloudTrail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws.ec2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-01-01T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"awsRegion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ModifySnapshotAttribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventSource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec2.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-01-01T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AwsApiCall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.05"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"recipientAccountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"requestID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"requestParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"attributeType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CREATE_VOLUME_PERMISSION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"createVolumePermission"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                          &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"snapshotId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"snap-1111"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"responseElements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"_return"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sourceIPAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"111.111.111.111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"userAgent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mozilla/2.0 (compatible; NEWT ActiveX; Win32)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"userIdentity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"accessKeyId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"accountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sts::123456789012:assumed-role/example-role/example-user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"principalId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"sessionContext"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"creationDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-01-01T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"mfaAuthenticated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"sessionIssuer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"accountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::123456789012:role/example-role"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"principalId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Role"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-role"&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"webIdFederationData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AssumedRole"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sample event makes it a little easier to write an &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html" rel="noopener noreferrer"&gt;Event Pattern&lt;/a&gt;, but a pattern could also be created from the information in the API specification to match fields and values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html" rel="noopener noreferrer"&gt;Sharing an EBS volume snapshot&lt;/a&gt; publicly modifies an existing snapshot with the &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html" rel="noopener noreferrer"&gt;ModifySnapshotAttribute&lt;/a&gt; API call. The &lt;code&gt;“group”: “all”&lt;/code&gt; key-value pair is added through &lt;code&gt;CreateVolumePermission&lt;/code&gt; during the API call.&lt;/p&gt;

&lt;p&gt;This solution will monitor for invocations of this call and, if it meets the Event Rule criteria &lt;code&gt;“group”: “all”&lt;/code&gt;, forward the event to a State Machine which will call the &lt;code&gt;ModifySnapshotAttribute&lt;/code&gt; API to make the snapshot private again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8261blg7vpczppmlu3db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8261blg7vpczppmlu3db.png" title="The Event to Step Function Workflow" alt="The Event to Step Function Workflow" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing an Event Pattern to Match
&lt;/h2&gt;

&lt;p&gt;This example will use Terraform to manage the Infrastructure as Code (IAC). Using Terraform will enable the ability to scale and deploy this solution in a predictable and repeatable state across multiple regions and AWS accounts.&lt;/p&gt;

&lt;p&gt;Event Patterns have a few &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html" rel="noopener noreferrer"&gt;fields&lt;/a&gt; that are always present. Writing the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule" rel="noopener noreferrer"&gt;CloudWatch Event Rule&lt;/a&gt; &lt;code&gt;event_pattern&lt;/code&gt; will use keys from from the above CloudTrail event. The source will be the service the event originates from, &lt;code&gt;aws.ec2&lt;/code&gt;, and detail-type, which is &lt;code&gt;AWS API Call via CloudTrail&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Terraform, the event rule and pattern is created as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_event_rule"&lt;/span&gt; &lt;span class="s2"&gt;"public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Capture events when Snapshots are made public"&lt;/span&gt;

  &lt;span class="nx"&gt;event_pattern&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ec2.amazonaws.com"],
    "eventName": [
        "ModifySnapshotAttribute"
    ],
    "requestParameters": {
      "createVolumePermission": {
        "add": {
          "items":
            {
            "group": ["all"]
            }
        }
      }
    }
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contained within the “detail” key is the CloudTrail log like shown above. Fields &lt;code&gt;eventSource&lt;/code&gt;, and &lt;code&gt;eventName&lt;/code&gt; help filter to the &lt;code&gt;ec2:ModifySnapshotAttribute&lt;/code&gt; permission.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;requestParameters&lt;/code&gt; section does not have to explicitly match everything contained in the log, and in this case, it is looking to match &lt;code&gt;“group”: “all”&lt;/code&gt;. When writing event patterns, the fields specified must match the event to trigger the rule.&lt;/p&gt;

&lt;p&gt;Multiple values can be specified within square brackets ( “[ ]” ), comma delimited, and the pattern will match on an “OR” basis to any of the values within.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html#eb-create-pattern" rel="noopener noreferrer"&gt;Create Event Patterns&lt;/a&gt; in the AWS Documentation website for more information on the logic used to match events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Triggering a State Machine
&lt;/h2&gt;

&lt;p&gt;Step Function workflows can be invoked directly from Eventbridge event rules. The full event object is sent as the payload.&lt;/p&gt;

&lt;p&gt;The event rule will require an IAM role to invoke the state machine. It requires a trust policy or “assume role policy” allowing &lt;code&gt;events.amazonaws.com&lt;/code&gt; to assume the role and the action &lt;code&gt;states:StartExecution&lt;/code&gt; on the yet to be created state machine. The state machine will be created later, but is easily referenced here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"event_public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-events-role"&lt;/span&gt;

  &lt;span class="nx"&gt;inline_policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-events-policy"&lt;/span&gt;
    &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Principal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"events.amazonaws.com"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"events_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"states:StartExecution"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sfn_state_machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target#argument-reference" rel="noopener noreferrer"&gt;event target in Terraform&lt;/a&gt; requires only 4 things: the rule referenced, a name for the target, the IAM role created above, as well as the state machine ARN reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_event_target"&lt;/span&gt; &lt;span class="s2"&gt;"sfn"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;rule&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_cloudwatch_event_rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;target_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-to-sfn"&lt;/span&gt;
  &lt;span class="nx"&gt;arn&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_sfn_state_machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event_public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Remediating the Public Snapshot
&lt;/h2&gt;

&lt;p&gt;Like the event target, the state machine will need an IAM role with the appropriate permissions to make the snapshot private.&lt;/p&gt;

&lt;p&gt;The state machines IAM role is similar to that of Events, this one with a &lt;code&gt;states.amazonaws.com&lt;/code&gt; trust policy and the &lt;code&gt;ec2:ModifySnapshotAttribute&lt;/code&gt; action. Resource requires a wildcard here as snapshot ARNs can be dynamically generated and the automation should encompass any snapshot created in the account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"sfn_public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-sfn-role"&lt;/span&gt;

  &lt;span class="nx"&gt;inline_policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-sfn-policy"&lt;/span&gt;
    &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sfn_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Principal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"states.amazonaws.com"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"sfn_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ec2:ModifySnapshotAttribute"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state machine itself is fairly simple. After it begins, it will run a single stage, which removes the public permission, and then exits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx620y2b971nziw79k2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx620y2b971nziw79k2z.png" title="The Step Function Workflow" alt="The Step Function Workflow" width="183" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating the definition of a state machine has a learning curve. Step Functions has a visual workflow designer in the AWS console that can help reduce some of the learning curve.&lt;/p&gt;

&lt;p&gt;There are some more complicated things to tie tasks together, transforming outputs into inputs, and forking the logic, but none of these are necessary for this example. Another helpful resource for in-depth information on Amazon States Language is hosted at &lt;a href="https://states-language.net/" rel="noopener noreferrer"&gt;https://states-language.net/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_sfn_state_machine"&lt;/span&gt; &lt;span class="s2"&gt;"public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot"&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sfn_public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;

  &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "Comment": "Removes group:all from snapshots",
  "StartAt": "RemoveAllPermission",
  "States": {
    "RemoveAllPermission": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:ec2:modifySnapshotAttribute",
      "Parameters": {
        "SnapshotId.$": "$.detail.requestParameters.snapshotId",
        "CreateVolumePermission": {
            "Remove": [ { "Group": "all" } ]
        }
      },
      "End": true
    }
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Walking through the state machine definition, it begins with a comment about what the state machine’s purpose is.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;StartAt&lt;/code&gt; refers to the starting point of the state machine and in this case, is the &lt;code&gt;RemoveAllPermission&lt;/code&gt; task.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RemoveAllPermission&lt;/code&gt; uses an AWS SDK resource in the form of &lt;code&gt;arn:aws:states:::aws-sdk:${SERVICE}:${API}&lt;/code&gt; . All of the currently available service integrations are listed in the&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html" rel="noopener noreferrer"&gt; AWS documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The keys in parameters match those required by the&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html" rel="noopener noreferrer"&gt; API call&lt;/a&gt;, and the &lt;code&gt;SnapshotId&lt;/code&gt; is retrieved from the CloudTrail Event in JSON format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;The full Terraform code is hosted in a Github snippet and includes all code above. Paired with an AWS provider block, this example can be deployed for testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/dgwhited/ce2f3570f5f7e79b2477456a62b2db38" rel="noopener noreferrer"&gt;https://gist.github.com/dgwhited/ce2f3570f5f7e79b2477456a62b2db38&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;###########################&lt;/span&gt;
&lt;span class="c1"&gt;#### Eventbridge event ####&lt;/span&gt;
&lt;span class="c1"&gt;###########################&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_event_rule"&lt;/span&gt; &lt;span class="s2"&gt;"public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Capture events when Snapshots are made public"&lt;/span&gt;

  &lt;span class="nx"&gt;event_pattern&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["ec2.amazonaws.com"],
    "eventName": [
        "ModifySnapshotAttribute"
    ],
    "requestParameters": {
      "createVolumePermission": {
        "add": {
          "items":
          {
            "group": ["all"]
          }
        }
      }
    }
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_event_target"&lt;/span&gt; &lt;span class="s2"&gt;"sfn"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;rule&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_cloudwatch_event_rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;target_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-to-sfn"&lt;/span&gt;
  &lt;span class="nx"&gt;arn&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_sfn_state_machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event_public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;###########################&lt;/span&gt;
&lt;span class="c1"&gt;##### Eventbridge IAM #####&lt;/span&gt;
&lt;span class="c1"&gt;###########################&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"event_public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-events-role"&lt;/span&gt;

  &lt;span class="nx"&gt;inline_policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-events-policy"&lt;/span&gt;
    &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Principal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"events.amazonaws.com"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"events_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"states:StartExecution"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sfn_state_machine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;###########################&lt;/span&gt;
&lt;span class="c1"&gt;###### State Machine ######&lt;/span&gt;
&lt;span class="c1"&gt;###########################&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_sfn_state_machine"&lt;/span&gt; &lt;span class="s2"&gt;"public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot"&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sfn_public_snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;

  &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "Comment": "Removes group:all from snapshots",
  "StartAt": "RemoveAllPermission",
  "States": {
    "RemoveAllPermission": {
      "Type": "Task",
      "Resource": "arn:aws:states:::aws-sdk:ec2:modifySnapshotAttribute",
      "Parameters": {
        "SnapshotId.$": "$.detail.requestParameters.snapshotId",
        "CreateVolumePermission": {
            "Remove": [ { "Group": "all" } ]
        }
      },
      "End": true
    }
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"sfn_public_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-sfn-role"&lt;/span&gt;

  &lt;span class="nx"&gt;inline_policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"public-snapshot-sfn-policy"&lt;/span&gt;
    &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sfn_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Principal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"states.amazonaws.com"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"sfn_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ec2:ModifySnapshotAttribute"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other Uses
&lt;/h2&gt;

&lt;p&gt;This example showed a single task that took action and ended upon receiving a qualified event. Other helpful extensions could be notifying a slack channel or user or creating tickets that action was taken. The Step Functions AWS SDK integration is a very powerful tool that can be used to create reactive controls that maintain a secure baseline in the event a preventative control should fail.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The information presented in this article is accurate as of March 02, 2022.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>security</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
