inspec 4.22.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +63 -0
  3. data/inspec.gemspec +36 -0
  4. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/Gemfile +11 -0
  5. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/inspec-plugin-template.gemspec +43 -0
  6. data/lib/plugins/inspec-init/templates/profiles/aws/README.md +192 -0
  7. data/lib/plugins/inspec-init/templates/profiles/aws/attributes.yml +2 -0
  8. data/lib/plugins/inspec-init/templates/profiles/aws/controls/example.rb +39 -0
  9. data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +22 -0
  10. data/lib/plugins/inspec-init/templates/profiles/azure/README.md +56 -0
  11. data/lib/plugins/inspec-init/templates/profiles/azure/controls/example.rb +14 -0
  12. data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +14 -0
  13. data/lib/plugins/inspec-init/templates/profiles/gcp/README.md +66 -0
  14. data/lib/plugins/inspec-init/templates/profiles/gcp/attributes.yml +2 -0
  15. data/lib/plugins/inspec-init/templates/profiles/gcp/controls/example.rb +27 -0
  16. data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +19 -0
  17. data/lib/resource_support/aws.rb +76 -0
  18. data/lib/resource_support/aws/aws_backend_base.rb +12 -0
  19. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -0
  20. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +24 -0
  21. data/lib/resource_support/aws/aws_resource_mixin.rb +69 -0
  22. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +27 -0
  23. data/lib/resources/aws/aws_billing_report.rb +107 -0
  24. data/lib/resources/aws/aws_billing_reports.rb +74 -0
  25. data/lib/resources/aws/aws_cloudtrail_trail.rb +97 -0
  26. data/lib/resources/aws/aws_cloudtrail_trails.rb +51 -0
  27. data/lib/resources/aws/aws_cloudwatch_alarm.rb +67 -0
  28. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +105 -0
  29. data/lib/resources/aws/aws_config_delivery_channel.rb +74 -0
  30. data/lib/resources/aws/aws_config_recorder.rb +99 -0
  31. data/lib/resources/aws/aws_ebs_volume.rb +127 -0
  32. data/lib/resources/aws/aws_ebs_volumes.rb +69 -0
  33. data/lib/resources/aws/aws_ec2_instance.rb +162 -0
  34. data/lib/resources/aws/aws_ec2_instances.rb +69 -0
  35. data/lib/resources/aws/aws_ecs_cluster.rb +88 -0
  36. data/lib/resources/aws/aws_eks_cluster.rb +105 -0
  37. data/lib/resources/aws/aws_elb.rb +85 -0
  38. data/lib/resources/aws/aws_elbs.rb +84 -0
  39. data/lib/resources/aws/aws_flow_log.rb +106 -0
  40. data/lib/resources/aws/aws_iam_access_key.rb +112 -0
  41. data/lib/resources/aws/aws_iam_access_keys.rb +153 -0
  42. data/lib/resources/aws/aws_iam_group.rb +62 -0
  43. data/lib/resources/aws/aws_iam_groups.rb +56 -0
  44. data/lib/resources/aws/aws_iam_password_policy.rb +121 -0
  45. data/lib/resources/aws/aws_iam_policies.rb +57 -0
  46. data/lib/resources/aws/aws_iam_policy.rb +311 -0
  47. data/lib/resources/aws/aws_iam_role.rb +60 -0
  48. data/lib/resources/aws/aws_iam_root_user.rb +82 -0
  49. data/lib/resources/aws/aws_iam_user.rb +145 -0
  50. data/lib/resources/aws/aws_iam_users.rb +160 -0
  51. data/lib/resources/aws/aws_kms_key.rb +100 -0
  52. data/lib/resources/aws/aws_kms_keys.rb +58 -0
  53. data/lib/resources/aws/aws_rds_instance.rb +74 -0
  54. data/lib/resources/aws/aws_route_table.rb +67 -0
  55. data/lib/resources/aws/aws_route_tables.rb +64 -0
  56. data/lib/resources/aws/aws_s3_bucket.rb +142 -0
  57. data/lib/resources/aws/aws_s3_bucket_object.rb +87 -0
  58. data/lib/resources/aws/aws_s3_buckets.rb +52 -0
  59. data/lib/resources/aws/aws_security_group.rb +314 -0
  60. data/lib/resources/aws/aws_security_groups.rb +71 -0
  61. data/lib/resources/aws/aws_sns_subscription.rb +82 -0
  62. data/lib/resources/aws/aws_sns_topic.rb +57 -0
  63. data/lib/resources/aws/aws_sns_topics.rb +60 -0
  64. data/lib/resources/aws/aws_sqs_queue.rb +66 -0
  65. data/lib/resources/aws/aws_subnet.rb +92 -0
  66. data/lib/resources/aws/aws_subnets.rb +56 -0
  67. data/lib/resources/aws/aws_vpc.rb +77 -0
  68. data/lib/resources/aws/aws_vpcs.rb +55 -0
  69. data/lib/resources/azure/azure_backend.rb +379 -0
  70. data/lib/resources/azure/azure_generic_resource.rb +55 -0
  71. data/lib/resources/azure/azure_resource_group.rb +151 -0
  72. data/lib/resources/azure/azure_virtual_machine.rb +262 -0
  73. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +131 -0
  74. metadata +202 -0
@@ -0,0 +1,74 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-rds"
4
+
5
+ class AwsRdsInstance < Inspec.resource(1)
6
+ name "aws_rds_instance"
7
+ desc "Verifies settings for an rds instance"
8
+ example <<~EXAMPLE
9
+ describe aws_rds_instance(db_instance_identifier: 'test-instance-id') do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsSingularResourceMixin
16
+ attr_reader :db_instance_identifier
17
+
18
+ def to_s
19
+ "RDS Instance #{@db_instance_identifier}"
20
+ end
21
+
22
+ private
23
+
24
+ def validate_params(raw_params)
25
+ validated_params = check_resource_param_names(
26
+ raw_params: raw_params,
27
+ allowed_params: [:db_instance_identifier],
28
+ allowed_scalar_name: :db_instance_identifier,
29
+ allowed_scalar_type: String
30
+ )
31
+ if validated_params.empty? || !validated_params.key?(:db_instance_identifier)
32
+ raise ArgumentError, "You must provide an id for the aws_rds_instance."
33
+ end
34
+
35
+ if validated_params.key?(:db_instance_identifier) && validated_params[:db_instance_identifier] !~ /^[a-z]{1}[0-9a-z\-]{0,62}$/
36
+ raise ArgumentError, "aws_rds_instance Database Instance ID must be in the format: start with a letter followed by up to 62 letters/numbers/hyphens."
37
+ end
38
+
39
+ validated_params
40
+ end
41
+
42
+ def fetch_from_api
43
+ backend = BackendFactory.create(inspec_runner)
44
+ dsg_response = nil
45
+ catch_aws_errors do
46
+ begin
47
+ dsg_response = backend.describe_db_instances(db_instance_identifier: db_instance_identifier)
48
+ @exists = true
49
+ rescue Aws::RDS::Errors::DBInstanceNotFound
50
+ @exists = false
51
+ return
52
+ end
53
+ end
54
+
55
+ if dsg_response.db_instances.empty?
56
+ @exists = false
57
+ return
58
+ end
59
+
60
+ @db_instance_identifier = dsg_response.db_instances[0].db_instance_identifier
61
+ end
62
+
63
+ # Uses the SDK API to really talk to AWS
64
+ class Backend
65
+ class AwsClientApi < AwsBackendBase
66
+ BackendFactory.set_default_backend(self)
67
+ self.aws_client_class = Aws::RDS::Client
68
+
69
+ def describe_db_instances(query)
70
+ aws_service_client.describe_db_instances(query)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,67 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-ec2"
4
+
5
+ class AwsRouteTable < Inspec.resource(1)
6
+ name "aws_route_table"
7
+ desc "Verifies settings for an AWS Route Table"
8
+ example <<~EXAMPLE
9
+ describe aws_route_table do
10
+ its('route_table_id') { should cmp 'rtb-05462d2278326a79c' }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsSingularResourceMixin
16
+
17
+ def to_s
18
+ "Route Table #{@route_table_id}"
19
+ end
20
+
21
+ attr_reader :route_table_id, :vpc_id
22
+
23
+ private
24
+
25
+ def validate_params(raw_params)
26
+ validated_params = check_resource_param_names(
27
+ raw_params: raw_params,
28
+ allowed_params: [:route_table_id],
29
+ allowed_scalar_name: :route_table_id,
30
+ allowed_scalar_type: String
31
+ )
32
+
33
+ if validated_params.key?(:route_table_id) &&
34
+ validated_params[:route_table_id] !~ /^rtb\-([0-9a-f]{17})|(^rtb\-[0-9a-f]{8})$/
35
+ raise ArgumentError,
36
+ "aws_route_table Route Table ID must be in the" \
37
+ ' format "rtb-" followed by 8 or 17 hexadecimal characters.'
38
+ end
39
+
40
+ validated_params
41
+ end
42
+
43
+ def fetch_from_api
44
+ backend = BackendFactory.create(inspec_runner)
45
+
46
+ if @route_table_id.nil?
47
+ args = nil
48
+ else
49
+ args = { filters: [{ name: "route-table-id", values: [@route_table_id] }] }
50
+ end
51
+
52
+ resp = backend.describe_route_tables(args)
53
+ routetable = resp.to_h[:route_tables]
54
+ @exists = !routetable.empty?
55
+ end
56
+
57
+ class Backend
58
+ class AwsClientApi < AwsBackendBase
59
+ BackendFactory.set_default_backend(self)
60
+ self.aws_client_class = Aws::EC2::Client
61
+
62
+ def describe_route_tables(query)
63
+ aws_service_client.describe_route_tables(query)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,64 @@
1
+ require "resource_support/aws/aws_plural_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-ec2"
4
+
5
+ class AwsRouteTables < Inspec.resource(1)
6
+ name "aws_route_tables"
7
+ desc "Verifies settings for AWS Route Tables in bulk"
8
+ example <<~EXAMPLE
9
+ describe aws_route_tables do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsPluralResourceMixin
16
+ # Underlying FilterTable implementation.
17
+ filter = FilterTable.create
18
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
19
+ filter.register_column(:vpc_ids, field: :vpc_id)
20
+ .register_column(:route_table_ids, field: :route_table_id)
21
+ filter.install_filter_methods_on_resource(self, :routes_data)
22
+
23
+ def routes_data
24
+ @table
25
+ end
26
+
27
+ def to_s
28
+ "Route Tables"
29
+ end
30
+
31
+ private
32
+
33
+ def validate_params(raw_criteria)
34
+ unless raw_criteria.is_a? Hash
35
+ raise "Unrecognized criteria for fetching Route Tables. " \
36
+ "Use 'criteria: value' format."
37
+ end
38
+
39
+ # No criteria yet
40
+ unless raw_criteria.empty?
41
+ raise ArgumentError, "aws_route_tables does not currently accept resource parameters."
42
+ end
43
+
44
+ raw_criteria
45
+ end
46
+
47
+ def fetch_from_api
48
+ backend = BackendFactory.create(inspec_runner)
49
+ catch_aws_errors do
50
+ @table = backend.describe_route_tables({}).to_h[:route_tables]
51
+ end
52
+ end
53
+
54
+ class Backend
55
+ class AwsClientApi < AwsBackendBase
56
+ BackendFactory.set_default_backend self
57
+ self.aws_client_class = Aws::EC2::Client
58
+
59
+ def describe_route_tables(query = {})
60
+ aws_service_client.describe_route_tables(query)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,142 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-s3"
4
+
5
+ class AwsS3Bucket < Inspec.resource(1)
6
+ name "aws_s3_bucket"
7
+ desc "Verifies settings for a s3 bucket"
8
+ example <<~EXAMPLE
9
+ describe aws_s3_bucket(bucket_name: 'test_bucket') do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsSingularResourceMixin
16
+ attr_reader :bucket_name, :has_default_encryption_enabled, :has_access_logging_enabled, :region
17
+
18
+ def to_s
19
+ "S3 Bucket #{@bucket_name}"
20
+ end
21
+
22
+ def bucket_acl
23
+ catch_aws_errors do
24
+ @bucket_acl ||= BackendFactory.create(inspec_runner).get_bucket_acl(bucket: bucket_name).grants
25
+ end
26
+ end
27
+
28
+ def bucket_policy
29
+ @bucket_policy ||= fetch_bucket_policy
30
+ end
31
+
32
+ # RSpec will alias this to be_public
33
+ def public?
34
+ # first line just for formatting
35
+ false || \
36
+ bucket_acl.any? { |g| g.grantee.type == "Group" && g.grantee.uri =~ /AllUsers/ } || \
37
+ bucket_acl.any? { |g| g.grantee.type == "Group" && g.grantee.uri =~ /AuthenticatedUsers/ } || \
38
+ bucket_policy.any? { |s| s.effect == "Allow" && s.principal == "*" }
39
+ end
40
+
41
+ def has_default_encryption_enabled?
42
+ return false unless @exists
43
+
44
+ @has_default_encryption_enabled ||= fetch_bucket_encryption_configuration
45
+ end
46
+
47
+ def has_access_logging_enabled?
48
+ return false unless @exists
49
+
50
+ catch_aws_errors do
51
+ @has_access_logging_enabled ||= !BackendFactory.create(inspec_runner).get_bucket_logging(bucket: bucket_name).logging_enabled.nil?
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def validate_params(raw_params)
58
+ validated_params = check_resource_param_names(
59
+ raw_params: raw_params,
60
+ allowed_params: [:bucket_name],
61
+ allowed_scalar_name: :bucket_name,
62
+ allowed_scalar_type: String
63
+ )
64
+ if validated_params.empty? || !validated_params.key?(:bucket_name)
65
+ raise ArgumentError, "You must provide a bucket_name to aws_s3_bucket."
66
+ end
67
+
68
+ validated_params
69
+ end
70
+
71
+ def fetch_from_api
72
+ backend = BackendFactory.create(inspec_runner)
73
+
74
+ # Since there is no basic "get_bucket" API call, use the
75
+ # region fetch as the existence check.
76
+ begin
77
+ @region = backend.get_bucket_location(bucket: bucket_name).location_constraint
78
+ rescue Aws::S3::Errors::NoSuchBucket
79
+ @exists = false
80
+ return
81
+ end
82
+ @exists = true
83
+ end
84
+
85
+ def fetch_bucket_policy
86
+ backend = BackendFactory.create(inspec_runner)
87
+ catch_aws_errors do
88
+ begin
89
+ # AWS SDK returns a StringIO, we have to read()
90
+ raw_policy = backend.get_bucket_policy(bucket: bucket_name).policy
91
+ return JSON.parse(raw_policy.read)["Statement"].map do |statement|
92
+ lowercase_hash = {}
93
+ statement.each_key { |k| lowercase_hash[k.downcase] = statement[k] }
94
+ @bucket_policy = OpenStruct.new(lowercase_hash)
95
+ end
96
+ rescue Aws::S3::Errors::NoSuchBucketPolicy
97
+ @bucket_policy = []
98
+ end
99
+ end
100
+ end
101
+
102
+ def fetch_bucket_encryption_configuration
103
+ @has_default_encryption_enabled ||= catch_aws_errors do
104
+ begin
105
+ !BackendFactory.create(inspec_runner)
106
+ .get_bucket_encryption(bucket: bucket_name)
107
+ .server_side_encryption_configuration
108
+ .nil?
109
+ rescue Aws::S3::Errors::ServerSideEncryptionConfigurationNotFoundError
110
+ false
111
+ end
112
+ end
113
+ end
114
+
115
+ # Uses the SDK API to really talk to AWS
116
+ class Backend
117
+ class AwsClientApi < AwsBackendBase
118
+ BackendFactory.set_default_backend(self)
119
+ self.aws_client_class = Aws::S3::Client
120
+
121
+ def get_bucket_acl(query)
122
+ aws_service_client.get_bucket_acl(query)
123
+ end
124
+
125
+ def get_bucket_location(query)
126
+ aws_service_client.get_bucket_location(query)
127
+ end
128
+
129
+ def get_bucket_policy(query)
130
+ aws_service_client.get_bucket_policy(query)
131
+ end
132
+
133
+ def get_bucket_logging(query)
134
+ aws_service_client.get_bucket_logging(query)
135
+ end
136
+
137
+ def get_bucket_encryption(query)
138
+ aws_service_client.get_bucket_encryption(query)
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,87 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-s3"
4
+
5
+ class AwsS3BucketObject < Inspec.resource(1)
6
+ name "aws_s3_bucket_object"
7
+ desc "Verifies settings for a s3 bucket object"
8
+ example <<~EXAMPLE
9
+ describe aws_s3_bucket_object(bucket_name: 'bucket_name', key: 'file_name') do
10
+ it { should exist }
11
+ it { should_not be_public }
12
+ end
13
+ EXAMPLE
14
+ supports platform: "aws"
15
+
16
+ include AwsSingularResourceMixin
17
+ attr_reader :bucket_name, :key
18
+
19
+ def to_s
20
+ # keep the format that aws uses.
21
+ "s3://#{@bucket_name}/#{@key}"
22
+ end
23
+
24
+ def object_acl
25
+ return @object_acl if defined? @object_acl
26
+
27
+ catch_aws_errors do
28
+ @object_acl = BackendFactory.create(inspec_runner).get_object_acl(bucket: bucket_name, key: key).grants
29
+ end
30
+ @object_acl
31
+ end
32
+
33
+ # RSpec will alias this to be_public
34
+ def public?
35
+ # first line just for formatting
36
+ false || \
37
+ object_acl.any? { |g| g.grantee.type == "Group" && g.grantee.uri =~ /AllUsers/ } || \
38
+ object_acl.any? { |g| g.grantee.type == "Group" && g.grantee.uri =~ /AuthenticatedUsers/ }
39
+ end
40
+
41
+ private
42
+
43
+ def validate_params(raw_params)
44
+ validated_params = check_resource_param_names(
45
+ raw_params: raw_params,
46
+ allowed_params: %i{bucket_name key id}
47
+ )
48
+ if validated_params.empty? || !validated_params.key?(:bucket_name) || !validated_params.key?(:key)
49
+ raise ArgumentError, "You must provide a bucket_name and key to aws_s3_bucket_object."
50
+ end
51
+
52
+ validated_params
53
+ end
54
+
55
+ def fetch_from_api
56
+ backend = BackendFactory.create(inspec_runner)
57
+ catch_aws_errors do
58
+ begin
59
+ # Just use get_object to detect if the bucket exists
60
+ backend.get_object(bucket: bucket_name, key: key)
61
+ rescue Aws::S3::Errors::NoSuchBucket
62
+ @exists = false
63
+ return
64
+ rescue Aws::S3::Errors::NoSuchKey
65
+ @exists = false
66
+ return
67
+ end
68
+ end
69
+ @exists = true
70
+ end
71
+
72
+ class Backend
73
+ class AwsClientApi < AwsBackendBase
74
+ BackendFactory.set_default_backend(self)
75
+ self.aws_client_class = Aws::S3::Client
76
+
77
+ # Used to detect if object exists
78
+ def get_object(query)
79
+ aws_service_client.get_object(query)
80
+ end
81
+
82
+ def get_object_acl(query)
83
+ aws_service_client.get_object_acl(query)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,52 @@
1
+ require "resource_support/aws/aws_plural_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-s3"
4
+
5
+ class AwsS3Buckets < Inspec.resource(1)
6
+ name "aws_s3_buckets"
7
+ desc "Verifies settings for AWS S3 Buckets in bulk"
8
+ example <<~EXAMPLE
9
+ describe aws_s3_bucket do
10
+ its('bucket_names') { should eq ['my_bucket'] }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsPluralResourceMixin
16
+
17
+ # Underlying FilterTable implementation.
18
+ filter = FilterTable.create
19
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
20
+ filter.register_column(:bucket_names, field: :name)
21
+ filter.install_filter_methods_on_resource(self, :table)
22
+
23
+ def to_s
24
+ "S3 Buckets"
25
+ end
26
+
27
+ def validate_params(resource_params)
28
+ unless resource_params.empty?
29
+ raise ArgumentError, "aws_s3_buckets does not accept resource parameters."
30
+ end
31
+
32
+ resource_params
33
+ end
34
+
35
+ private
36
+
37
+ def fetch_from_api
38
+ backend = BackendFactory.create(inspec_runner)
39
+ @table = backend.list_buckets.buckets.map(&:to_h)
40
+ end
41
+
42
+ class Backend
43
+ class AwsClientApi < AwsBackendBase
44
+ BackendFactory.set_default_backend self
45
+ self.aws_client_class = Aws::S3::Client
46
+
47
+ def list_buckets
48
+ aws_service_client.list_buckets
49
+ end
50
+ end
51
+ end
52
+ end