DEV Community

Emily Johnson
Emily Johnson

Posted on

Cut AWS Costs by 90%: How We Saved Big and Gained Flexibility

Hold on to your seat!

Believe it or not, we made a surprising U-turn after activating AWS Config across five of our AWS accounts. We decided to disable all but two of our Config rules. But what led to this drastic move?

Let's take a step back. If you're new to AWS Config, it's a service offered by AWS that evaluates the configuration settings of your AWS resources. This is achieved by enabling AWS Config rules in one or multiple of your AWS accounts to check your configuration settings against best practices or your desired/approved settings.

At the time of writing, there are over 80 managed rules available. These rules provide a solid foundation for a configuration audit. However, not all rules are applicable, depending on your environments and use cases. Internally at LifeOmic, we selected 21 out of those and enabled them last year.

Now, let's dive into the reasons behind disabling most of them last week.

Slashing AWS Config Costs by 90%

For the five AWS accounts on which we've enabled Config, the service is costing us a staggering $3,300 per month, or around $40,000 a year. This was significantly higher than anticipated, especially for a lean startup like ours. Enabling across all ten AWS accounts, we would likely have doubled that.

Image title

Luckily, we've started using JupiterOne. With the J1QL queries and the latest alerts capability, we decided to configure the equivalent of AWS Config evaluations using JupiterOne instead. Out of the 21 Config rules we've previously enabled, 19 of those can already be replaced. This move has not only reduced our costs but also given us more flexibility. As a matter of fact, we've saved 90% on costs by ditching AWS Config - a move that has been a game-changer for us. You can read more about our experience on carsnewstoday.com.

AWS Config Rule Supported by J1 query/alert
acm-certificate-expiration-check Yes
ec2-instances-in-vpc Yes
ec2-volume-inuse-check Yes
encrypted-volumes Yes
restricted-ssh Yes
iam-root-access-key-check Yes
iam-password-policy Yes
iam-user-no-policies-check Yes
lambda-function-settings-check Yes
db-instance-backup-enabled Yes
rds-snapshots-public-prohibited Yes
rds-storage-encrypted Yes
dynamodb-throughput-limit-check No
s3-bucket-public-read-prohibited Yes
s3-bucket-public-write-prohibited Yes
s3-bucket-replication-enabled Yes
s3-bucket-server-side-encryption-enabled Yes
s3-bucket-ssl-requests-only No
s3-bucket-logging-enabled Yes
s3-bucket-versioning-enabled Yes
cloudtrail-enabled Yes

For further details, please consult our documentation page and the alerts rule pack on GitHub.

We preserved two rules that are currently incompatible with JupiterOne J1QL queries and alerts. However, given JupiterOne's existing integration with AWS Config, we developed a "fallback" J1QL alert rule to identify non-compliant Config rule evaluations:

JupiterOne Alert Rule
name config-rule-noncompliant
description AWS Config rule evaluation found non-compliant resource configurations.
query Find aws_config_rule with complianceState='NON_COMPLIANT'
condition When query result count > 0

This approach allowed us to minimize our dependence on AWS Config rules, limiting them to only those necessary, while maintaining consistent and centralized configuration alerts within JupiterOne. As a result, we achieved a remarkable 90% reduction in our AWS bill for the Config service.

Was this effort solely driven by cost savings? While that's certainly a welcome benefit, it's not the only motivation.

Improved Adaptability in Customization

Previously, with AWS Config rules, it was challenging to incorporate additional contextual filters into the rule configuration to minimize false positives.

For instance, the “s3-bucket-public-read-prohibited” rule from AWS Config does not accept any additional parameters.

What if I have certain S3 buckets hosting public resources and, therefore, are intended to be publicly readable?

With JupiterOne’s query, it’s straightforward to fine-tune those out by adding the classification property/tag filter to the J1QL query:

Find aws_s3_bucket with classification != 'public'
  that ALLOWS as grant Everyone where grant.permission='READ'

Similarly, if we want to take into account additional contexts such as production status and classification label for “s3-bucket-replication-enabled” and “s3-bucket-versioning-enabled,” we can add those filters easily to the J1QL query:

// s3-bucket-replication-enabled
// find production buckets that do not have replication enabled
Find aws_s3_bucket with tag.Production = true
  and (replicationEnabled != true or destinationBuckets = undefined)

// s3-bucket-versioning-enabled
// find production buckets classified as critical without versioning or
// mfaDelete enabled
Find aws_s3_bucket
  with tag.Production = true and classification = ’critical’
  and (versioningEnabled != true or mfaDelete != true)

We can apply the same pattern to easily tune any rule to reduce false positives. We did the same for the “fallback” config-rule-noncompliantrule:

Find aws_config_rule with compliant = false
  that evaluates * with
    tag.Production = true or
    classification = ‘critical’ or
    criticality >= 9

Additionally, we leverage the power of relationships from the JupiterOne knowledge graph to create more precise targets. For example, we can correlate users who have been assigned access to our production AWS accounts via SAML single sign-on, the user’s endpoint devices, and the compliance status on those devices to create a query/alert only when those privileged users have endpoints that fall out of compliance:

Find HostAgent with compliant!=true
  that monitors (Host|Device)
  that owns Person
  that is User
  that (assigned|has)
    (aws_iam_role|aws_iam_policy|aws_iam_user_policy|aws_iam_group)
    with tag.Production=true

As an aside, for the curious, here's a glimpse of the graph generated by the above query:

Graphical representation

Streamlined Complexity

The JupiterOne data model's inherent abstract class labeling enables us to harness the power of abstract rules, thereby minimizing the number of rules to be managed and alerts to be analyzed. To illustrate this point:

For example, if we aim to verify whether our production data stores have enabled encryption universally, we might require a single AWS Config rule to cover each data store type:

  • S3 buckets
  • RDS instances
  • DynamoDB tables
  • EBS volumes

Notably, within JupiterOne, all of the above entities have been assigned an abstract class label: DataStore.  This allows us to utilize a single alert rule instead of four, covering everything. Moreover, as needed, we can apply the same tag/property filter to reduce false positives.

Find DataStore with 
  tag.Production = true and 
  classification = ’critical’ and
  encrypted != true

Another example illustrates this concept further. With thousands of security findings from various types of security scanners, agents, and monitoring tools, how do we set up alerts for the most critical ones? By leveraging the abstract entity labeling and graph relationships in JupiterOne, we can achieve something like:

Find (Device|Host|Database|Application|CodeRepo) with
  tag.Production = true or classification = ’critical’
that has Finding with severity = ‘critical’ or numericSeverity > 7

This single query encompasses real-time threat detection from AWS Inspector, GuardDuty, application code scanning solutions like Veracode and WhiteHat, and endpoint monitoring tools like Carbon Black and SentinelOne. Moreover, JupiterOne boasts seamless, out-of-the-box integrations with all of these platforms, providing a unified view of our security posture.

Centralized Alert Management and Notification Hub

In the past, receiving alerts from AWS Config evaluations required a complex setup involving CloudWatch, alarms, and SNS and/or SES notifications. This entailed coordinating multiple services, and we would have had to replicate this process for each of the half dozen other security controls we had implemented. Furthermore, when alerts were triggered, we would have to visit the dashboard/console of each individual system to view them, resulting in a fragmented and time-consuming process.

With JupiterOne, we have streamlined all alerts within a single platform. The Alerts app provides a unified view of alerts, findings, and vulnerabilities from all integrated sources, enabling us to set up notifications and perform in-depth analysis in one place. This is still in its early stages of development, but here is a sneak preview of what's to come.

Unified Alert Management

That’s it. We’ve moved on from AWS Config and have no regrets whatsoever.

Top comments (0)