inspec-iggy 0.5.0 → 0.6.0

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.
@@ -0,0 +1,42 @@
1
+ # helpers for working with InSpec-AWS profiles
2
+
3
+ require 'yaml'
4
+
5
+ module InspecPlugins::Iggy::Platforms
6
+ class AwsHelper
7
+ # find the additional parameters
8
+ AWS_RESOURCE_QUALIFIERS = {
9
+ }.freeze
10
+
11
+ # the iterators for the various resource types
12
+ AWS_RESOURCE_ITERATORS = {
13
+ }.freeze
14
+
15
+ AWS_REMOVED_PROPERTIES = {
16
+ }.freeze
17
+
18
+ # Terraform boilerplate controls/controls.rb content
19
+ def self.tf_controls
20
+ "\n\naws_vpc_id = attribute('aws_vpc_id', default: '', description: 'Optional AWS VPC identifier.')\n\n"
21
+ end
22
+
23
+ # readme content
24
+ def self.readme
25
+ end
26
+
27
+ # inspec.yml boilerplate content from
28
+ # inspec/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml
29
+ def self.inspec_yml
30
+ yml = {}
31
+ yml['inspec_version'] = '~> 4'
32
+ yml['depends'] = [{
33
+ 'name' => 'inspec-aws',
34
+ 'url' => 'https://github.com/inspec/inspec-aws/archive/master.tar.gz'
35
+ }]
36
+ yml['supports'] = [{
37
+ 'platform' => 'aws'
38
+ }]
39
+ yml
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ # helpers for working with InSpec-Azure profiles
2
+
3
+ require 'yaml'
4
+
5
+ module InspecPlugins::Iggy::Platforms
6
+ class AzureHelper
7
+ # find the additional parameters
8
+ AZURE_RESOURCE_QUALIFIERS = {
9
+ }.freeze
10
+
11
+ # the iterators for the various resource types
12
+ AZURE_RESOURCE_ITERATORS = {
13
+ }.freeze
14
+
15
+ AZURE_REMOVED_PROPERTIES = {
16
+ }.freeze
17
+
18
+ # readme content
19
+ def self.readme
20
+ "\n"
21
+ end
22
+
23
+ # inspec.yml boilerplate content from
24
+ # inspec/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml
25
+ def self.inspec_yml
26
+ yml = {}
27
+ yml['inspec_version'] = '>= 2.2.7'
28
+ yml['depends'] = [{
29
+ 'name' => 'inspec-azure',
30
+ 'url' => 'https://github.com/inspec/inspec-azure/archive/master.tar.gz'
31
+ }]
32
+ yml['supports'] = [{
33
+ 'platform' => 'azure'
34
+ }]
35
+ yml
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,168 @@
1
+ # helpers for working with InSpec-GCP profiles
2
+
3
+ require 'yaml'
4
+
5
+ module InspecPlugins::Iggy::Platforms
6
+ class GcpHelper
7
+ # find the additional parameters for the 'describe'
8
+ GCP_RESOURCE_QUALIFIERS = {
9
+ 'google_bigquery_dataset' => [:project, :name],
10
+ 'google_bigquery_table' => [:project, :dataset, :name],
11
+ 'google_cloudfunctions_cloud_function' => [:project, :location, :name],
12
+ 'google_compute_address' => [:project, :location, :name],
13
+ 'google_compute_autoscaler' => [:project, :zone, :name],
14
+ 'google_compute_backend_bucket' => [:project, :name],
15
+ 'google_compute_backend_service' => [:project, :name],
16
+ 'google_compute_disk' => [:project, :name, :zone],
17
+ 'google_compute_firewall' => [:project, :name],
18
+ 'google_compute_forwarding_rule' => [:project, :region, :name],
19
+ 'google_compute_global_address' => [:project, :name],
20
+ 'google_compute_global_forwarding_rule' => [:project, :name],
21
+ 'google_compute_health_check' => [:project, :name],
22
+ 'google_compute_http_health_check' => [:project, :name],
23
+ 'google_compute_https_health_check' => [:project, :name],
24
+ 'google_compute_image' => [:project, :name],
25
+ 'google_compute_instance' => [:project, :zone, :name],
26
+ 'google_compute_instance_group' => [:project, :zone, :name],
27
+ 'google_compute_instance_group_manager' => [:project, :zone, :name],
28
+ 'google_compute_instance_template' => [:project, :name],
29
+ 'google_compute_network' => [:project, :name],
30
+ 'google_compute_project_info' => [:project],
31
+ 'google_compute_region' => [:project, :name],
32
+ 'google_compute_region_backend_service' => [:project, :region, :name],
33
+ 'google_compute_region_instance_group_manager' => [:project, :region, :name],
34
+ 'google_compute_route' => [:project, :name],
35
+ 'google_compute_router' => [:project, :region, :name],
36
+ 'google_compute_snapshot' => [:project, :name],
37
+ 'google_compute_ssl_certificate' => [:project, :name],
38
+ 'google_compute_ssl_policy' => [:project, :name],
39
+ 'google_compute_subnetwork' => [:project, :region, :name],
40
+ 'google_compute_subnetwork_iam_policy' => [:project, :region, :name],
41
+ 'google_compute_target_http_proxy' => [:project, :name],
42
+ 'google_compute_target_https_proxy' => [:project, :name],
43
+ 'google_compute_target_pool' => [:project, :region, :name],
44
+ 'google_compute_target_tcp_proxy' => [:project, :name],
45
+ 'google_compute_url_map' => [:project, :name],
46
+ 'google_compute_vpn_tunnel' => [:project, :region, :name],
47
+ 'google_compute_zone' => [:project, :zone],
48
+ 'google_container_cluster' => [:project, :zone, :name],
49
+ 'google_container_node_pool' => [:project, :zone, :cluster_name, :nodepool_name],
50
+ 'google_container_regional_cluster' => [:project, :location, :name],
51
+ 'google_container_regional_node_pool' => [:project, :location, :cluster, :name],
52
+ 'google_dns_managed_zone' => [:project, :zone],
53
+ 'google_dns_resource_record_set' => [:project, :name, :type, :managed_zone],
54
+ 'google_kms_crypto_key' => [:project, :location, :key_ring_name, :name],
55
+ 'google_kms_crypto_key_iam_binding' => [:crypto_key_url, :role],
56
+ 'google_kms_key_ring' => [:project, :location, :name],
57
+ 'google_kms_key_ring_iam_binding' => [:key_ring_url, :role],
58
+ 'google_logging_project_exclusion' => [:project, :exclusion],
59
+ 'google_logging_project_sink' => [:project, :sink],
60
+ 'google_organization' => [:display_name],
61
+ 'google_organization_policy' => [:name, :constraints],
62
+ 'google_project' => [:project],
63
+ 'google_project_alert_policy' => [:policy],
64
+ 'google_project_alert_policy_condition' => [:name, :filter],
65
+ 'google_project_iam_binding' => [:project, :role],
66
+ 'google_project_iam_custom_role' => [:project, :name],
67
+ 'google_project_logging_audit_config' => [:project],
68
+ 'google_project_metric' => [:project, :metric],
69
+ 'google_pubsub_subscription' => [:project, :name],
70
+ 'google_pubsub_subscription_iam_policy' => [:project, :name],
71
+ 'google_pubsub_topic' => [:project, :name],
72
+ 'google_pubsub_topic_iam_policy' => [:project, :name],
73
+ 'google_resourcemanager_organization_policy' => [:organization_name, :constraint],
74
+ 'google_service_account' => [:name],
75
+ 'google_service_account_key' => [:name],
76
+ 'google_sourcerepo_repository' => [:project, :name],
77
+ 'google_sql_database_instance' => [:project, :database],
78
+ 'google_storage_bucket' => [:name],
79
+ 'google_storage_bucket_acl' => [:bucket, :entity],
80
+ 'google_storage_bucket_iam_binding' => [:bucket, :role],
81
+ 'google_storage_bucket_object' => [:bucket, :object],
82
+ 'google_storage_default_object_acl' => [:bucket, :entity],
83
+ 'google_storage_object_acl' => [:bucket, :object, :entity],
84
+ 'google_user' => [:user_key]
85
+ }.freeze
86
+
87
+ # the iterators for the various resource types
88
+ GCP_RESOURCE_ITERATORS = {
89
+ # 'google_compute_disk' => { 'iterator' => 'google_compute_disks', 'index' => 'names', 'qualifiers' => [:project, :zone] }, # false positives because instance attached disks aren't managed by Terraform
90
+ # 'google_compute_network' => { 'iterator' => 'google_compute_networks', 'index' => 'network_names', 'qualifiers' => [:project] },
91
+ # 'google_compute_region' => { 'iterator' => 'google_compute_regions', 'index' => 'region_names', 'qualifiers' => [:project] },
92
+ # 'google_compute_region_instance_group_manager' => { 'iterator' => 'google_compute_region_instance_group_managers', 'index' => 'instance_group_names', 'qualifiers' => [:project, :region] }, verify it has 2 filter criteria
93
+ # 'google_compute_route' => { 'iterator' => 'google_compute_routes', 'index' => 'names', 'qualifiers' => [:project] },
94
+ # 'google_compute_subnetwork' => { 'iterator' => 'google_compute_subnetworks', 'index' => 'subnetwork_names', 'qualifiers' => [:project, :region] },
95
+ # 'google_compute_zone' => { 'iterator' => 'google_compute_zones', 'index' => 'zone_names', 'qualifiers' => [:project] },
96
+ # 'google_kms_crypto_key_iam_binding' => { 'iterator' => 'google_kms_crypto_key_iam_bindings', 'index' => 'iam_binding_roles', 'qualifiers' => [:crypto_key_url] },
97
+ # 'google_kms_key_ring' => { 'iterator' => 'google_kms_key_rings', 'index' => 'key_ring_names', 'qualifiers' => [:project, :location] },
98
+ # 'google_kms_key_ring_iam_binding' => { 'iterator' => 'google_kms_key_ring_iam_bindings', 'index' => 'iam_binding_roles', 'qualifiers' => [:key_ring_url] },
99
+ # 'google_organization' => { 'iterator' => 'google_organizations', 'index' => 'names', 'qualifiers' => [] }, # organizations are not managed by Terraform
100
+ # 'google_project' => { 'iterator' => 'google_projects', 'index' => 'project_names', 'qualifiers' => [] }, # projects are not managed by Terraform
101
+ # 'google_project_iam_binding' => { 'iterator' => 'google_project_iam_bindings', 'index' => 'iam_binding_roles', 'qualifiers' => [:project] },
102
+ 'google_bigquery_dataset' => { 'iterator' => 'google_bigquery_datasets', 'index' => 'names', 'qualifiers' => [:project] },
103
+ 'google_bigquery_table' => { 'iterator' => 'google_bigquery_tables', 'index' => 'table_references', 'qualifiers' => [:project, :dataset] },
104
+ 'google_cloudbuild_trigger' => { 'iterator' => 'google_cloudbuild_triggers', 'index' => 'names', 'qualifiers' => [:project] },
105
+ 'google_cloudfunctions_cloud_function' => { 'iterator' => 'google_cloudfunctions_cloud_functions', 'index' => 'names', 'qualifiers' => [:project, :location] },
106
+ 'google_compute_autoscaler' => { 'iterator' => 'google_compute_autoscalers', 'index' => 'names', 'qualifiers' => [:project, :zone] },
107
+ 'google_compute_backend_bucket' => { 'iterator' => 'google_compute_backend_buckets', 'index' => 'names', 'qualifiers' => [:project] },
108
+ 'google_compute_backend_service' => { 'iterator' => 'google_compute_backend_services', 'index' => 'names', 'qualifiers' => [:project] },
109
+ 'google_compute_firewall' => { 'iterator' => 'google_compute_firewalls', 'index' => 'firewall_names', 'qualifiers' => [:project] },
110
+ 'google_compute_forwarding_rule' => { 'iterator' => 'google_compute_forwarding_rules', 'index' => 'forwarding_rule_names', 'qualifiers' => [:project, :region] },
111
+ 'google_compute_health_check' => { 'iterator' => 'google_compute_health_checks', 'index' => 'names', 'qualifiers' => [:project] },
112
+ 'google_compute_http_health_check' => { 'iterator' => 'google_compute_http_health_checks', 'index' => 'names', 'qualifiers' => [:project] },
113
+ 'google_compute_https_health_check' => { 'iterator' => 'google_compute_https_health_checks', 'index' => 'names', 'qualifiers' => [:project] },
114
+ 'google_compute_instance' => { 'iterator' => 'google_compute_instances', 'index' => 'instance_names', 'qualifiers' => [:project, :zone] },
115
+ 'google_compute_instance_group' => { 'iterator' => 'google_compute_instance_groups', 'index' => 'instance_group_names', 'qualifiers' => [:project, :zone] },
116
+ 'google_compute_instance_group_manager' => { 'iterator' => 'google_compute_instance_group_managers', 'index' => 'base_instance_names', 'qualifiers' => [:project, :zone] },
117
+ 'google_compute_instance_template' => { 'iterator' => 'google_compute_instance_templates', 'index' => 'names', 'qualifiers' => [:project] },
118
+ 'google_compute_router' => { 'iterator' => 'google_compute_routers', 'index' => 'names', 'qualifiers' => [:project, :region] },
119
+ 'google_compute_snapshot' => { 'iterator' => 'google_compute_snapshots', 'index' => 'names', 'qualifiers' => [:project] },
120
+ 'google_compute_ssl_certificate' => { 'iterator' => 'google_compute_ssl_certificates', 'index' => 'names', 'qualifiers' => [:project] },
121
+ 'google_compute_ssl_policy' => { 'iterator' => 'google_compute_ssl_policies', 'index' => 'names', 'qualifiers' => [:project] },
122
+ 'google_compute_target_http_proxy' => { 'iterator' => 'google_compute_target_http_proxies', 'index' => 'names', 'qualifiers' => [:project] },
123
+ 'google_compute_target_https_proxy' => { 'iterator' => 'google_compute_target_https_proxies', 'index' => 'names', 'qualifiers' => [:project] },
124
+ 'google_compute_target_pool' => { 'iterator' => 'google_compute_target_pools', 'index' => 'names', 'qualifiers' => [:project, :region] },
125
+ 'google_compute_target_tcp_proxy' => { 'iterator' => 'google_compute_target_tcp_proxies', 'index' => 'names', 'qualifiers' => [:project] },
126
+ 'google_compute_url_map' => { 'iterator' => 'google_compute_url_maps', 'index' => 'names', 'qualifiers' => [:project] },
127
+ 'google_compute_vpn_tunnel' => { 'iterator' => 'google_compute_vpn_tunnels', 'index' => 'vpn_tunnel_names', 'qualifiers' => [:project, :region] },
128
+ 'google_container_cluster' => { 'iterator' => 'google_container_clusters', 'index' => 'cluster_names', 'qualifiers' => [:project, :zone] },
129
+ 'google_container_node_pool' => { 'iterator' => 'google_container_node_pools', 'index' => 'node_pool_names', 'qualifiers' => [:project, :zone, :cluster_name] },
130
+ 'google_container_regional_cluster' => { 'iterator' => 'google_container_regional_clusters', 'index' => 'names', 'qualifiers' => [:project, :location] },
131
+ 'google_dns_managed_zone' => { 'iterator' => 'google_dns_managed_zones', 'index' => 'zone_names', 'qualifiers' => [:project] },
132
+ 'google_dns_resource_record_set' => { 'iterator' => 'google_dns_resource_record_sets', 'index' => 'names', 'qualifiers' => [:project, :managed_zone] },
133
+ 'google_kms_crypto_key' => { 'iterator' => 'google_kms_crypto_keys', 'index' => 'crypto_key_names', 'qualifiers' => [:project, :location, :key_ring_name] },
134
+ 'google_logging_project_sink' => { 'iterator' => 'google_logging_project_sinks', 'index' => 'sink_names', 'qualifiers' => [:project] },
135
+ 'google_project_alert_policy' => { 'iterator' => 'google_project_alert_policies', 'index' => 'policy_names', 'qualifiers' => [:project] },
136
+ 'google_project_metric' => { 'iterator' => 'google_project_metrics', 'index' => 'metric_names', 'qualifiers' => [:project] },
137
+ 'google_pubsub_subscription' => { 'iterator' => 'google_pubsub_subscriptions', 'index' => 'names', 'qualifiers' => [:project] },
138
+ }.freeze
139
+
140
+ GCP_REMOVED_PROPERTIES = {
141
+ 'google_compute_http_health_check' => [:self_link, :id, :creation_timestamp], # id: terraform has name not id, self_link: undocumented but broken, creation_timestamp api incompatibility
142
+ 'google_compute_instance' => [:label_fingerprint, :machine_type, :min_cpu_platform, :zone], # label_fingerprint, machine_type, zone api incompatibility | min_cpu_platform undefined
143
+ 'google_compute_instance_group' => [:zone], # zone api incompatibility issue
144
+ 'google_compute_forwarding_rule' => [:backend_service, :ip_version, :network, :region, :subnetwork], # :backend_service, :ip_version, :network, :region, :subnetwork api incompatibility
145
+ 'google_compute_target_pool' => [:backup_pool, :failover_ratio, :id, :region, :self_link], # api incompatibility
146
+
147
+ }.freeze
148
+
149
+ # readme content
150
+ def self.readme
151
+ end
152
+
153
+ # inspec.yml boilerplate content from
154
+ # inspec/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml
155
+ def self.inspec_yml
156
+ yml = {}
157
+ yml['inspec_version'] = '>= 2.3.5'
158
+ yml['depends'] = [{
159
+ 'name' => 'inspec-gcp',
160
+ 'url' => 'https://github.com/inspec/inspec-gcp/archive/master.tar.gz'
161
+ }]
162
+ yml['supports'] = [{
163
+ 'platform' => 'gcp'
164
+ }]
165
+ yml
166
+ end
167
+ end
168
+ end
@@ -1,46 +1,64 @@
1
+ # -*- coding: utf-8 -*-
1
2
  # renders the profile from the parsed files
2
3
 
3
4
  require 'yaml'
4
5
 
6
+ require 'inspec-iggy/platforms/aws_helper'
7
+ require 'inspec-iggy/platforms/azure_helper'
8
+ require 'inspec-iggy/platforms/gcp_helper'
9
+
5
10
  module InspecPlugins
6
11
  module Iggy
7
12
  class ProfileHelper
8
13
  # match the output of 'inspec init profile'
9
- def self.render_profile(cli_ui, options, source_file, controls)
14
+ # inspec/lib/plugins/inspec-init/lib/inspec-init/renderer.rb
15
+ def self.render_profile(cli, options, source_file, controls, platform = nil)
10
16
  name = options[:name]
11
17
  overwrite_mode = options[:overwrite]
12
- # Create new profile at /Users/mattray/ws/inspec-iggy/foobar
13
- full_destination_root_path = Pathname.new(Dir.pwd).join(name)
14
- cli_ui.plain_text "Create new profile at #{cli_ui.mark_text(full_destination_root_path)}"
15
- if File.exist?(full_destination_root_path) && !overwrite_mode
16
- cli_ui.plain_text "#{cli_ui.mark_text(full_destination_root_path)} exists already, use --overwrite"
17
- cli_ui.exit(1)
18
+
19
+ # --------------------------- InSpec Code Generator ---------------------------
20
+ cli.headline('InSpec Iggy Code Generator')
21
+
22
+ full_destination_path = Pathname.new(Dir.pwd).join(name)
23
+
24
+ if File.exist?(full_destination_path) && !overwrite_mode
25
+ cli.plain_line "#{cli.emphasis(full_destination_path)} exists already, use --overwrite"
26
+ cli.exit(1)
18
27
  end
19
- # ensure that full_destination_root_path directory is available
20
- FileUtils.mkdir_p(full_destination_root_path)
21
- # * Create directory controls
22
- cli_ui.li "Create directory #{cli_ui.mark_text("#{name}/controls")}"
28
+
29
+ # ensure that full_destination_path directory is available
30
+ FileUtils.mkdir_p(full_destination_path)
31
+
32
+ # Creating new profile at /Users/mattray/ws/inspec-iggy/FOO
33
+ cli.plain_line "Creating new profile at #{cli.emphasis(full_destination_path)}"
34
+ # * Creating file README.md
35
+ render_readme_md(cli, name, source_file, platform)
36
+ # * Creating directory controls
37
+ cli.list_item "Creating directory #{cli.emphasis('controls')}"
23
38
  FileUtils.mkdir_p("#{name}/controls")
24
- render_readme_md(cli_ui, name, source_file)
25
- render_inspec_yml(cli_ui, name, source_file, options)
26
- render_controls_rb(cli_ui, name, controls)
39
+ # * Creating file controls/generated.rb
40
+ render_controls_rb(cli, name, controls)
41
+ # * Creating file inspec.yml
42
+ render_inspec_yml(cli, name, source_file, options, platform)
43
+ cli.plain_line
27
44
  end
28
45
 
29
- # * Create file README.md
30
- def self.render_readme_md(cli_ui, name, source_file)
31
- render_file = "#{name}/README.md"
32
- cli_ui.li "Create file #{cli_ui.mark_text(render_file)}"
33
- f = File.new(render_file, 'w')
46
+ def self.render_readme_md(cli, name, source_file, platform)
47
+ cli.list_item "Creating file #{cli.emphasis('README.md')}"
48
+ f = File.new("#{name}/README.md", 'w')
34
49
  f.puts("# #{name}")
35
50
  f.puts
36
51
  f.puts("This profile was generated by InSpec-Iggy v#{Iggy::VERSION} from the #{source_file} source file.")
52
+
53
+ f.puts(InspecPlugins::Iggy::Platforms::AwsHelper.readme) if platform.eql?('aws')
54
+ f.puts(InspecPlugins::Iggy::Platforms::AzureHelper.readme) if platform.eql?('azure')
55
+ f.puts(InspecPlugins::Iggy::Platforms::GcpHelper.readme) if platform.eql?('gcp')
56
+
37
57
  f.close
38
58
  end
39
59
 
40
- # * Create file inspec.yml
41
- def self.render_inspec_yml(cli_ui, name, source_file, options)
42
- render_file = "#{name}/inspec.yml"
43
- cli_ui.li "Create file #{cli_ui.mark_text(render_file)}"
60
+ def self.render_inspec_yml(cli, name, source_file, options, platform)
61
+ cli.list_item "Creating file #{cli.emphasis('inspec.yml')}"
44
62
  yml = {}
45
63
  yml['name'] = name
46
64
  yml['title'] = options[:title]
@@ -51,16 +69,19 @@ module InspecPlugins
51
69
  yml['summary'] = options[:summary]
52
70
  yml['version'] = options[:version]
53
71
  yml['description'] = "Generated by InSpec-Iggy v#{Iggy::VERSION} from the #{source_file} source file."
54
- f = File.new(render_file, 'w')
72
+
73
+ yml.merge!(InspecPlugins::Iggy::Platforms::AwsHelper.inspec_yml) if platform.eql?('aws')
74
+ yml.merge!(InspecPlugins::Iggy::Platforms::AzureHelper.inspec_yml) if platform.eql?('azure')
75
+ yml.merge!(InspecPlugins::Iggy::Platforms::GcpHelper.inspec_yml) if platform.eql?('gcp')
76
+
77
+ f = File.new("#{name}/inspec.yml", 'w')
55
78
  f.write(yml.to_yaml)
56
79
  f.close
57
80
  end
58
81
 
59
- # * Create file controls/controls.rb
60
- def self.render_controls_rb(cli_ui, name, controls)
61
- render_file = "#{name}/controls/controls.rb"
62
- cli_ui.li "Create file #{cli_ui.mark_text(render_file)}"
63
- f = File.new(render_file, 'w')
82
+ def self.render_controls_rb(cli, name, controls)
83
+ cli.list_item "Creating file #{cli.emphasis('controls/generated.rb')}"
84
+ f = File.new("#{name}/controls/generated.rb", 'w')
64
85
  f.write(controls)
65
86
  f.close
66
87
  end
@@ -4,7 +4,8 @@ require 'inspec/plugin/v2'
4
4
 
5
5
  require 'inspec-iggy/version'
6
6
  require 'inspec-iggy/profile_helper'
7
- require 'inspec-iggy/terraform/parser'
7
+ require 'inspec-iggy/terraform/generate'
8
+ require 'inspec-iggy/terraform/negative'
8
9
 
9
10
  module InspecPlugins::Iggy
10
11
  module Terraform
@@ -20,71 +21,95 @@ module InspecPlugins::Iggy
20
21
  say("Iggy v#{InspecPlugins::Iggy::VERSION}")
21
22
  end
22
23
 
23
- option :debug,
24
- desc: 'Verbose debugging messages',
25
- type: :boolean,
26
- default: false
24
+ class_option :debug,
25
+ desc: 'Verbose debugging messages',
26
+ type: :boolean,
27
+ default: false
27
28
 
28
- option :copyright,
29
- desc: 'Name of the copyright holder',
30
- default: 'The Authors'
29
+ class_option :copyright,
30
+ desc: 'Name of the copyright holder',
31
+ default: 'The Authors'
31
32
 
32
- option :email,
33
- desc: 'Email address of the author',
34
- default: 'you@example.com'
33
+ class_option :email,
34
+ desc: 'Email address of the author',
35
+ default: 'you@example.com'
35
36
 
36
- option :license,
37
- desc: 'License for the profile',
38
- default: 'Apache-2.0'
37
+ class_option :license,
38
+ desc: 'License for the profile',
39
+ default: 'Apache-2.0'
39
40
 
40
- option :maintainer,
41
- desc: 'Name of the copyright holder',
42
- default: 'The Authors'
41
+ class_option :maintainer,
42
+ desc: 'Name of the copyright holder',
43
+ default: 'The Authors'
43
44
 
44
- option :summary,
45
- desc: 'One line summary for the profile',
46
- default: 'An InSpec Compliance Profile'
45
+ class_option :summary,
46
+ desc: 'One line summary for the profile',
47
+ default: 'An InSpec Compliance Profile'
47
48
 
48
- option :title,
49
- desc: 'Human-readable name for the profile',
50
- default: 'InSpec Profile'
49
+ class_option :title,
50
+ desc: 'Human-readable name for the profile',
51
+ default: 'InSpec Profile'
51
52
 
52
- option :version,
53
- desc: 'Specify the profile version',
54
- default: '0.1.0'
53
+ class_option :version,
54
+ desc: 'Specify the profile version',
55
+ default: '0.1.0'
55
56
 
56
- option :overwrite,
57
- desc: 'Overwrites existing profile directory',
58
- type: :boolean,
59
- default: false
57
+ class_option :overwrite,
58
+ desc: 'Overwrites existing profile directory',
59
+ type: :boolean,
60
+ default: false
60
61
 
61
- option :name,
62
- aliases: '-n',
63
- required: true,
64
- desc: 'Name of profile to be generated'
62
+ class_option :name,
63
+ aliases: '-n',
64
+ required: true,
65
+ desc: 'Name of profile to be generated'
65
66
 
66
- option :tfstate,
67
- aliases: '-t',
68
- desc: 'Specify path to the input terraform.tfstate',
69
- default: 'terraform.tfstate'
67
+ class_option :tfstate,
68
+ aliases: '-t',
69
+ desc: 'Specify path to the input terraform.tfstate',
70
+ default: 'terraform.tfstate'
71
+
72
+ class_option :platform,
73
+ desc: 'The InSpec platform providing the necessary resources (aws, azure, or gcp)'
74
+
75
+ class_option :resourcepath,
76
+ desc: 'Specify path to the InSpec Resource Pack providing the necessary resources'
70
77
 
71
78
  desc 'generate [options]', 'Generate InSpec compliance controls from terraform.tfstate'
72
79
  def generate
73
80
  Inspec::Log.level = :debug if options[:debug]
74
- generated_controls = InspecPlugins::Iggy::Terraform::Parser.parse_generate(options[:tfstate])
75
- printable_controls = InspecPlugins::Iggy::InspecHelper.tf_controls(options[:title], generated_controls)
76
- InspecPlugins::Iggy::ProfileHelper.render_profile(self, options, options[:tfstate], printable_controls)
81
+ platform = options[:platform]
82
+ resource_path = options[:resourcepath]
83
+ # require validation that if platform or resourcepath are passed, both are available
84
+ if platform or resource_path
85
+ unless platform and resource_path
86
+ error 'You must pass both --platform and --resourcepath if using either'
87
+ exit(1)
88
+ end
89
+ end
90
+ generated_controls = InspecPlugins::Iggy::Terraform::Generate.parse_generate(options[:tfstate], resource_path, platform)
91
+ printable_controls = InspecPlugins::Iggy::InspecHelper.tf_controls(options[:title], generated_controls, platform)
92
+ InspecPlugins::Iggy::ProfileHelper.render_profile(ui, options, options[:tfstate], printable_controls, platform)
77
93
  exit 0
78
94
  end
79
95
 
80
- # disabled extract functionality
81
- # desc 'extract [options]', 'Extract tagged InSpec profiles from terraform.tfstate'
82
- # def extract
83
- # Inspec::Log.level = :debug if options[:debug]
84
- # extracted_profiles = InspecPlugins::Iggy::Terraform::Parser.parse_extract(options[:tfstate])
85
- # puts InspecPlugins::Iggy::InspecHelper.print_commands(extracted_profiles)
86
- # exit 0
87
- # end
96
+ desc 'negative [options]', 'Generate negative InSpec compliance controls from terraform.tfstate'
97
+ def negative
98
+ Inspec::Log.level = :debug if options[:debug]
99
+ platform = options[:platform]
100
+ resource_path = options[:resourcepath]
101
+ # require validation that if platform or resourcepath are passed, both are available
102
+ if platform or resource_path
103
+ unless platform and resource_path
104
+ error 'You must pass both --platform and --resourcepath if using either'
105
+ exit(1)
106
+ end
107
+ end
108
+ negative_controls = InspecPlugins::Iggy::Terraform::Negative.parse_negative(options[:tfstate], resource_path, platform)
109
+ printable_controls = InspecPlugins::Iggy::InspecHelper.tf_controls(options[:title], negative_controls, platform)
110
+ InspecPlugins::Iggy::ProfileHelper.render_profile(ui, options, options[:tfstate], printable_controls, platform)
111
+ exit 0
112
+ end
88
113
  end
89
114
  end
90
115
  end