diff --git a/docs/resources/aws_s3_buckets.md.erb b/docs/resources/aws_s3_buckets.md.erb
new file mode 100644
index 000000000..4415909d9
--- /dev/null
+++ b/docs/resources/aws_s3_buckets.md.erb
@@ -0,0 +1,53 @@
+---
+title: About the aws_s3_buckets Resource
+---
+
+# aws\_s3\_buckets
+
+Use the `aws_s3_buckets` InSpec audit resource to list all buckets in a single account.
+
+Use the `aws_s3_bucket` InSpec audit resource to perform in-depth auditing of a single S3 bucket.
+
+
+
+## Syntax
+
+An `aws_s3_buckets` resource block takes no arguments
+
+ describe aws_s3_buckets do
+ it { should exist }
+ end
+
+
+
+## Examples
+
+The following examples show how to use this InSpec audit resource.
+
+As this is the initial release of `aws_s3_buckets`, its limited functionality precludes examples.
+
+
+
+## Matchers
+
+### exists
+
+The control will pass if the resource contains at least one bucket.
+
+ # Test if there are any buckets
+ describe aws_s3_buckets
+ it { should exist }
+ end
+
+## Properties
+
+### bucket\_names
+
+Provides an array of strings containing the names of the buckets.
+
+ # Examine what buckets have been created.
+ describe aws_s3_buckets do
+ its('bucket_names') { should eq ['my_bucket'] }
+ # OR
+ its('bucket_names') { should include 'my_bucket' }
+ end
diff --git a/lib/resource_support/aws.rb b/lib/resource_support/aws.rb
index 1ca0df14e..c412d2468 100644
--- a/lib/resource_support/aws.rb
+++ b/lib/resource_support/aws.rb
@@ -36,6 +36,7 @@ require 'resources/aws/aws_rds_instance'
require 'resources/aws/aws_route_table'
require 'resources/aws/aws_s3_bucket'
require 'resources/aws/aws_s3_bucket_object'
+require 'resources/aws/aws_s3_buckets'
require 'resources/aws/aws_security_group'
require 'resources/aws/aws_security_groups'
require 'resources/aws/aws_sns_subscription'
diff --git a/lib/resources/aws/aws_s3_buckets.rb b/lib/resources/aws/aws_s3_buckets.rb
new file mode 100644
index 000000000..e9426a746
--- /dev/null
+++ b/lib/resources/aws/aws_s3_buckets.rb
@@ -0,0 +1,51 @@
+# author: Matthew Dromazos
+# author: Sam Cornwell
+class AwsS3Buckets < Inspec.resource(1)
+ name 'aws_s3_buckets'
+ desc 'Verifies settings for AWS S3 Buckets in bulk'
+ example "
+ describe aws_s3_bucket do
+ its('bucket_names') { should eq ['my_bucket'] }
+ end
+ "
+ supports platform: 'aws'
+
+ include AwsPluralResourceMixin
+
+ # Underlying FilterTable implementation.
+ filter = FilterTable.create
+ filter.add_accessor(:where)
+ .add_accessor(:entries)
+ .add(:exists?) { |x| !x.entries.empty? }
+ .add(:bucket_names, field: :name)
+ filter.connect(self, :table)
+
+ def to_s
+ 'S3 Buckets'
+ end
+
+ def validate_params(resource_params)
+ unless resource_params.empty?
+ raise ArgumentError, 'aws_s3_buckets does not accept resource parameters.'
+ end
+ resource_params
+ end
+
+ private
+
+ def fetch_from_api
+ backend = BackendFactory.create(inspec_runner)
+ @table = backend.list_buckets.buckets.map(&:to_h)
+ end
+
+ class Backend
+ class AwsClientApi < AwsBackendBase
+ BackendFactory.set_default_backend self
+ self.aws_client_class = Aws::S3::Client
+
+ def list_buckets
+ aws_service_client.list_buckets
+ end
+ end
+ end
+end
diff --git a/test/integration/aws/default/verify/controls/aws_s3_buckets.rb b/test/integration/aws/default/verify/controls/aws_s3_buckets.rb
new file mode 100644
index 000000000..d40668690
--- /dev/null
+++ b/test/integration/aws/default/verify/controls/aws_s3_buckets.rb
@@ -0,0 +1,28 @@
+fixtures = {}
+[
+ 's3_bucket_public_name',
+ 's3_bucket_private_name',
+].each do |fixture_name|
+ fixtures[fixture_name] = attribute(
+ fixture_name,
+ default: "default.#{fixture_name}",
+ description: 'See ../build/s3.tf',
+ )
+end
+
+control "aws_s3_buckets recall" do
+
+ # You should be able to test if there are any buckets
+ describe aws_s3_buckets do
+ it { should exist }
+ end
+end
+
+control "aws_s3_buckets properties" do
+ # you should be able to test the cidr_block of a subnet
+ describe aws_s3_buckets do
+ its('bucket_names') { should include fixtures['s3_bucket_public_name'], fixtures['s3_bucket_private_name'] }
+ its('bucket_names') { should_not include 'i_dont_exist' }
+ end
+end
+
diff --git a/test/unit/resources/aws_s3_buckets_test.rb b/test/unit/resources/aws_s3_buckets_test.rb
new file mode 100644
index 000000000..6dbc07ac8
--- /dev/null
+++ b/test/unit/resources/aws_s3_buckets_test.rb
@@ -0,0 +1,88 @@
+require 'helper'
+
+# MSBB = MockS3BucketsBackend
+# Abbreviation not used outside this file
+
+#=============================================================================#
+# Constructor Tests
+#=============================================================================#
+class AwsS3BucketsConstructor < Minitest::Test
+ def setup
+ AwsS3Buckets::BackendFactory.select(AwsMSBB::Basic)
+ end
+
+ def test_constructor_no_args_ok
+ AwsS3Buckets.new
+ end
+
+ def test_constructor_reject_unknown_resource_params
+ assert_raises(ArgumentError) { AwsS3Buckets.new(bla: 'blabla') }
+ end
+end
+
+#=============================================================================#
+# Search / Recall
+#=============================================================================#
+class AwsS3BucketsRecallEmptyTest < Minitest::Test
+
+ def setup
+ AwsS3Buckets::BackendFactory.select(AwsMSBB::Empty)
+ end
+
+ def test_search_miss_via_empty_vpcs
+ refute AwsS3Buckets.new.exists?
+ end
+end
+
+class AwsS3BucketsRecallBasicTest < Minitest::Test
+
+ def setup
+ AwsS3Buckets::BackendFactory.select(AwsMSBB::Basic)
+ end
+
+ def test_search_hit_via_empty_filter
+ assert AwsS3Buckets.new.exists?
+ end
+end
+
+#=============================================================================#
+# Properties
+#=============================================================================#
+class AwsS3bucketsProperties < Minitest::Test
+ def setup
+ AwsS3Buckets::BackendFactory.select(AwsMSBB::Basic)
+ end
+
+ def test_property_bucket_names
+ basic = AwsS3Buckets.new
+ assert_kind_of(Array, basic.bucket_names)
+ assert(basic.bucket_names.include?('bucket-01'))
+ assert(!basic.bucket_names.include?('NonExistentBucket'))
+ refute(basic.bucket_names.include?(nil))
+ end
+end
+
+#=============================================================================#
+# Test Fixtures
+#=============================================================================#
+module AwsMSBB
+ class Empty < AwsBackendBase
+ def list_buckets
+ OpenStruct.new({ buckets: [] })
+ end
+ end
+
+ class Basic < AwsBackendBase
+ def list_buckets
+ fixtures = [
+ OpenStruct.new({
+ name: "bucket-01",
+ }),
+ OpenStruct.new({
+ name: "bucket-02",
+ }),
+ ]
+ OpenStruct.new({ buckets: fixtures })
+ end
+ end
+end