AWS Config is a service provided by AWS that can be used to evaluate the configuration settings of your AWS resources. This is typically done by enabling AWS Config rules in one or multiple of your AWS accounts to represent your ideal configuration settings.
There are a few downsides of AWS Config:
It can easily cost $500 to $1000+ per account per month depending on the number of resources in the account and number of rules you have configured.
It is hard to fine tune AWS Config rules with the tags and other contextual data to reduce false positives.
Setting up alerts and notifications requires additional configuration using SNS or CloudWatch.
Fortunately, almost all of evaluation of AWS Config rules can be done by a simple J1QL query/alert in JupiterOne. Additionally, each query can easily be modified to include tags or even relationship context.
Here are some examples.
Ensures ACM Certificates in your account are marked for expiration within the specified number of days.
Find aws_acm_certificate with expiresOn < date.now + 30days OR Find Certificate with expiresOn < date.now + 30days
Ensure all EC2 instances run in a VPC.
Find aws_instance with vpcId=undefined
Checks whether EBS volumes are attached to EC2 instances.
Find aws_ebs_volume that !USES aws_instance
Checks whether the EBS volumes that are in an attached state are encrypted.
Find aws_instance as i that USES aws_ebs_volume with encrypted!=true as v return i.tag.AccountName, i.name, i.instanceId, i.state, i.region, i.webLink, v.volumeId, v.encrypted, v.webLink
Checks whether the incoming SSH traffic for the security groups is accessible.
With AWS Config, this rule is compliant when the IP addresses of the incoming SSH traffic in the security groups are restricted. This rule applies only to IPv4.
Find aws_security_group as sg that ALLOWS as rule * as src where rule.ingress=true and rule.ipProtocol='tcp' and (rule.fromPort<=22 and rule.toPort>=22) return sg.displayName, rule.ipProtocol, rule.fromPort, rule.toPort, src.displayName, src.ipAddress, src.CIDR
Ensure root AWS account has MFA enabled.
Find aws_account with _source!='system-mapper' and mfaEnabled!=true
Checks whether the root user access key is available.
Find aws_account with _source!='system-mapper' and rootUserAccessKeyEnabled!=false
Ensure the account password policy for IAM users meets the specified requirements.
Find aws_iam_account_password_policy with requireUppercase != true or requireLowercase != true or requireSymbols != true or requireNumbers != true or minLength < 8 or maxAgeDays > 90 or historyCount < 12
Adjust the above values to match your organization policy. You can also separate each into its own query.
Ensure that none of your IAM users have policies attached.
IAM users should inherit permissions from IAM groups or roles.
Find aws_iam_user that assigned (aws_iam_user_policy|aws_iam_policy)
aws_iam_user_policy in the above query specifies an inline policy whereas
aws_iam_policy is a managed policy.
Checks whether the AWS Lambda function policy attached to the Lambda resource prohibits public access.
Find aws_lambda_function with runtime='nodejs6.10' Find aws_lambda_function with timeout < 5 or timeout > 300 Find aws_lambda_function with memorySize <= 128 or memorySize >= 1024 Find aws_lambda_function with role = '<role_arn>'
You can of course adjust any of the values in the above example queries.
nodejs6.10 is End-of-Life (EOL) as of April 2019.
The first query above is an excellent check to ensure you have migrated all of
your lambda functions to
Checks whether RDS DB instances have backups enabled.
Find (aws_db_instance|aws_rds_cluster) with backupRetentionPeriod=undefined
Optionally, the rule checks the backup retention period and the backup window.
Find (aws_db_instance|aws_rds_cluster) with backupRetentionPeriod=undefined or backupRetentionPeriod<30
Check whether the Amazon RDS clusters and instances are publicly accessible.
Find (aws_db_instance|aws_rds_cluster) with public=true
Checks if Amazon Relational Database Service (Amazon RDS) snapshots are public. The rule is non-compliant if any existing and new Amazon RDS snapshots are public.
Find (aws_db_snapshot|aws_db_cluster_snapshot) with public=true
Checks whether storage encryption is enabled for your RDS DB instances.
Find (aws_db_instance|aws_rds_cluster) with encrypted!=true
See a visual graph of which RDS cluster/instance is using which KMS key with the following query:
Find (aws_db_instance|aws_rds_cluster) that uses aws_kms_key return tree
You can easily extend the query to cover other data stores and check for their encryption status across the board:
Find DataStore with encrypted!=true
The above query covers RDS instances/clusters, S3 buckets, EBS volumes, DynamoDB tables, Redshift clusters all at once.
This is often combined with some tagging to reduce false positives. For example:
Find DataStore with encrypted!=true and (classification='critical' or classification='confidential')
Checks whether provisioned DynamoDB throughput is approaching the maximum limit for your account. By default, the rule checks if provisioned throughput exceeds a threshold of 80% of your account limits.
Checks that your Amazon S3 buckets do not allow public read access.
Find aws_s3_bucket that ALLOWS as grant Everyone where grant.permission='READ'
Or, to return certain specific properties about the bucket and the rule:
Find aws_s3_bucket as bucket that ALLOWS as grant everyone where grant.permission='READ' return bucket.displayName, bucket.tag.AccountName, grant.permission, grant.granteeType, grant.granteeURI
Checks that your Amazon S3 buckets do not allow public write access.
Find aws_s3_bucket that ALLOWS as grant Everyone where grant.permission='WRITE'
Checks whether S3 buckets have cross-region replication enabled.
Find aws_s3_bucket with replicationEnabled != true or destinationBuckets = undefined
Checks whether server side encryption is enabled for your S3 buckets.
Find aws_s3_bucket with encrypted=false and defaultEncryptionEnabled=false
Checks whether S3 buckets have policies that require requests to use Secure Socket Layer (SSL/TLS).
Find aws_s3_bucket with secureTransport != true
Checks whether logging is enabled for your S3 buckets.
Find aws_s3_bucket with loggingEnabled != true
Checks whether versioning is enabled for your S3 buckets. Optionally, the rule checks if MFA delete is enabled for your S3 buckets.
Find aws_s3_bucket with versioningEnabled != true or mfaDelete != true
Ensure CloudTrail is enabled.
Find aws_account that !HAS aws_cloudtrail