inspec 4.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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