inspec-iggy 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +8 -6
- data/README.md +91 -40
- data/inspec-iggy.gemspec +13 -13
- data/lib/inspec-iggy.rb +11 -2
- data/lib/inspec-iggy/cloudformation/cli_command.rb +92 -0
- data/lib/inspec-iggy/cloudformation/parser.rb +106 -0
- data/lib/inspec-iggy/inspec_helper.rb +62 -40
- data/lib/inspec-iggy/plugin.rb +43 -0
- data/lib/inspec-iggy/profile.rb +74 -0
- data/lib/inspec-iggy/terraform/cli_command.rb +94 -0
- data/lib/inspec-iggy/terraform/parser.rb +147 -0
- data/lib/inspec-iggy/version.rb +4 -4
- metadata +13 -16
- data/lib/inspec-iggy/cli.rb +0 -53
- data/lib/inspec-iggy/cloudformation.rb +0 -104
- data/lib/inspec-iggy/terraform.rb +0 -146
- data/test/bad.json +0 -6
- data/test/bjc-demo-aws-4.5.4.json +0 -851
- data/test/main.tf +0 -156
- data/test/outputs.tf +0 -11
- data/test/terraform.tfstate +0 -383
- data/test/variables.tf +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77411a21b6c3a1f74cdc23ab20f48d96af93a985
|
4
|
+
data.tar.gz: 0b32db4421f119d92343a7cd834e2953989ee3b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eac8bdf420cb4951742c5e66038bfda33c7776d7c75b78fab08f8cff81c18883c956670991ea62a8c4822a290bb24981db267b93ca68a5aa0487db57ee0462ce
|
7
|
+
data.tar.gz: b01d470916ca825f4a30cc3376a3979815160efd76fe2ee6d1ecae8b98d6881b937b6fa139a050719b6b38dcd9c056e725a6984b4e389ad862be2d16af179279
|
data/Gemfile
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
source
|
2
|
+
source 'http://rubygems.org'
|
3
3
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :test do
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
7
|
+
gem 'rake' # Build task manager
|
8
|
+
gem 'chefstyle'
|
9
|
+
gem 'byebug' # A debugger REPL
|
10
|
+
gem 'rubocop' # Needed for style linting
|
11
|
+
gem 'm'
|
10
12
|
end
|
11
13
|
|
12
14
|
group :tools do
|
13
|
-
gem
|
14
|
-
gem
|
15
|
+
gem 'github_changelog_generator'
|
16
|
+
gem 'rb-readline'
|
15
17
|
end
|
data/README.md
CHANGED
@@ -1,53 +1,61 @@
|
|
1
1
|
# Description #
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status Master](https://travis-ci.org/inspec/inspec-iggy.svg?branch=master)](https://travis-ci.org/inspec/inspec-iggy)
|
4
4
|
|
5
|
-
Iggy
|
5
|
+
InSpec-Iggy (InSpec Generate -> "IG" -> "Iggy") is an [InSpec](https://inspec.io) plugin for generating compliance controls and profiles from [Terraform](https://terraform.io) `tfstate` files and [AWS CloudFormation](https://aws.amazon.com/cloudformation/) templates. Iggy generates InSpec controls by mapping Terraform and CloudFormation resources to InSpec resources and exports a profile that may be used from the `inspec` CLI or uploaded to [Chef Automate](https://automate.chef.io/).
|
6
6
|
|
7
|
-
|
7
|
+
inspec terraform generate -n myprofile
|
8
|
+
inspec exec myprofile -t aws://us-west-2
|
9
|
+
inspec compliance upload myprofile
|
8
10
|
|
9
|
-
|
11
|
+
Iggy was originally a stand-alone CLI inspired by Christoph Hartmann's [inspec-verify-provision](https://github.com/chris-rock/inspec-verify-provision) and the blog post on testing [InSpec for provisioning testing: Verify Terraform setups with InSpec](http://lollyrock.com/articles/inspec-terraform/).
|
10
12
|
|
11
|
-
|
13
|
+
The [CHANGELOG.md](https://github.com/inspec/iggy/blob/master/CHANGELOG.md) covers current, previous and future development milestones and contains the features backlog.
|
12
14
|
|
13
|
-
|
15
|
+
1. [Requirements](#requirements)
|
16
|
+
2. [Installation](#installation)
|
17
|
+
3. [InSpec Terraform Generate](#itg)
|
18
|
+
4. [InSpec Terraform Extract](#ite)
|
19
|
+
5. [InSpec Cloudformation Generate](#icg)
|
20
|
+
6. [Testing](#testing)
|
14
21
|
|
15
|
-
#
|
22
|
+
# Requirements <a name="requirements"></a>
|
16
23
|
|
17
|
-
|
24
|
+
Iggy generates compliance profiles for InSpec 2.3 and later, which includes the AWS and Azure resources. Because resources are continuing to be added to InSpec, you may want the latest version to support as many resource coverage as possible. It has currently been tested primarily with AWS but other InSpec-supported platforms should work as well.
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
gem install inspec-iggy
|
23
|
-
inspec terraform version
|
24
|
-
```
|
26
|
+
Written and tested with Ruby 2.5.1.
|
27
|
+
|
28
|
+
# Installation <a name="installation"></a>
|
25
29
|
|
26
|
-
|
30
|
+
`inspec-iggy` is a plugin for InSpec. InSpec 2.3 or later is required. To install, use:
|
27
31
|
|
28
|
-
```
|
29
|
-
|
30
|
-
git clone git@github.com:inspec/inspec-iggy ~/inspec-iggy
|
31
|
-
mkdir -p ~/.inspec/plugins
|
32
|
-
ln -s ~/inspec-iggy/ ~/.inspec/plugins/inspec-iggy
|
33
|
-
inspec terraform version
|
32
|
+
```
|
33
|
+
$ inspec plugin install inspec-iggy
|
34
34
|
```
|
35
35
|
|
36
|
-
|
36
|
+
# InSpec Terraform Generate<a name="itg"></a>
|
37
37
|
|
38
|
-
|
39
|
-
# Build the `inspec-iggy` then install:
|
40
|
-
git clone https://github.com/inspec/inspec-iggy && cd inspec-iggy && gem build *gemspec && gem install *gem
|
41
|
-
inspec terraform version
|
42
|
-
```
|
38
|
+
inspec terraform generate --tfstate terraform.tfstate --name myprofile
|
43
39
|
|
44
|
-
|
40
|
+
Iggy dynamically pulls the available AWS resources from InSpec and attempts to map them to Terraform resources, producing an InSpec profile. ```inspec terraform generate --help``` will show all available options.
|
45
41
|
|
46
|
-
|
42
|
+
## Usage
|
47
43
|
|
48
|
-
|
44
|
+
inspec terraform generate [options] -n, --name=NAME
|
49
45
|
|
50
|
-
|
46
|
+
-n, --name=NAME Name of profile to be generated (required)
|
47
|
+
-t, [--tfstate=TFSTATE] Specify path to the input terraform.tfstate (default: .)
|
48
|
+
[--debug], [--no-debug] Verbose debugging messages
|
49
|
+
[--copyright=COPYRIGHT] Name of the copyright holder (default: The Authors)
|
50
|
+
[--email=EMAIL] Email address of the author (default: you@example.com)
|
51
|
+
[--license=LICENSE] License for the profile (default: Apache-2.0)
|
52
|
+
[--maintainer=MAINTAINER] Name of the copyright holder (default: The Authors)
|
53
|
+
[--summary=SUMMARY] One line summary for the profile (default: An InSpec Compliance Profile)
|
54
|
+
[--title=TITLE] Human-readable name for the profile (default: InSpec Profile)
|
55
|
+
[--version=VERSION] Specify the profile version (default: 0.1.0)
|
56
|
+
[--overwrite], [--no-overwrite] Overwrites existing profile directory
|
57
|
+
|
58
|
+
# InSpec Terraform Extract (EXPERIMENTAL)<a name="ite"></a>
|
51
59
|
|
52
60
|
inspec terraform extract --tfstate terraform.tfstate
|
53
61
|
|
@@ -78,27 +86,70 @@ Currently it only supports URL-based compliance profiles. InSpec supports other
|
|
78
86
|
|
79
87
|
inspec exec https://github.com/dev-sec/linux-baseline -t ssh://clckwrk@52.33.203.34 -i ~/.ssh/mattray-apac
|
80
88
|
|
81
|
-
# CloudFormation
|
89
|
+
# InSpec CloudFormation Generate<a name="icg"></a>
|
90
|
+
|
91
|
+
inspec cloudformation generate --template mytemplate.json --stack mystack-20180909T052147Z --profile myprofile
|
92
|
+
|
93
|
+
Iggy supports AWS CloudFormation templates by mapping the AWS resources to InSpec resources and using the stack name or unique stack ID associated with the CloudFormation template as an entry point to check those resources in the generated profile. ```inspec cloudformation generate --help``` will show all available options.
|
94
|
+
|
95
|
+
## Usage
|
96
|
+
|
97
|
+
inspec cloudformation generate [options] -n, --name=NAME -s, --stack=STACK -t, --template=TEMPLATE
|
98
|
+
|
99
|
+
-n, --name=NAME Name of profile to be generated (required)
|
100
|
+
-s, --stack=STACK Specify stack name or unique stack ID associated with the CloudFormation template
|
101
|
+
-t, --template=TEMPLATE Specify path to the input CloudFormation template
|
102
|
+
[--debug], [--no-debug] Verbose debugging messages
|
103
|
+
[--copyright=COPYRIGHT] Name of the copyright holder (default: The Authors)
|
104
|
+
[--email=EMAIL] Email address of the author (default: you@example.com)
|
105
|
+
[--license=LICENSE] License for the profile (default: Apache-2.0)
|
106
|
+
[--maintainer=MAINTAINER] Name of the copyright holder (default: The Authors)
|
107
|
+
[--summary=SUMMARY] One line summary for the profile (default: An InSpec Compliance Profile)
|
108
|
+
[--title=TITLE] Human-readable name for the profile (default: InSpec Profile)
|
109
|
+
[--version=VERSION] Specify the profile version (default: 0.1.0)
|
110
|
+
[--overwrite], [--no-overwrite] Overwrites existing profile directory
|
111
|
+
|
112
|
+
# Development
|
113
|
+
|
114
|
+
## Installation
|
115
|
+
|
116
|
+
To point `inspec` at a local copy of `inspec-iggy` for development, use:
|
117
|
+
|
118
|
+
```
|
119
|
+
$ inspec plugin install path/to/your/inspec-iggy/lib/inspec-iggy.rb
|
120
|
+
```
|
121
|
+
|
122
|
+
# Testing Iggy<a name="testing"></a>
|
82
123
|
|
83
|
-
**CloudFormation support has been started, but it is incomplete while focusing on Terraform.** Here is an example of the current output, note that it's not tied to an actual deployed CloudFormation Stack, so that will need to be provided for the entry point of testing.
|
84
|
-
https://gist.github.com/c4d6eda82dfb25502ef381cc631a1edd
|
85
124
|
|
86
|
-
|
125
|
+
Unit, Functional, and Integration tests are provided, though more are welcome. Iggy uses the Minitest library for testing, using the classic `def test...` syntax. Because Iggy loads InSpec into memory, and InSpec uses RSpec internally, Spec-style testing breaks.
|
87
126
|
|
88
|
-
|
127
|
+
To run all tests, run
|
128
|
+
|
129
|
+
```
|
130
|
+
$ bundle exec rake test
|
131
|
+
```
|
89
132
|
|
90
|
-
|
133
|
+
Linting is also provided via Rubocop.
|
91
134
|
|
92
|
-
|
135
|
+
To check for code style issues, run:
|
93
136
|
|
94
|
-
|
137
|
+
```
|
138
|
+
$ bundle exec rake lint
|
139
|
+
```
|
140
|
+
|
141
|
+
You can auto-correct many issues:
|
142
|
+
|
143
|
+
```
|
144
|
+
$ bundle exec rubocop -a
|
145
|
+
```
|
95
146
|
|
96
147
|
# License and Author #
|
97
148
|
|
98
149
|
| | |
|
99
150
|
|:---------------|:------------------------------------------|
|
100
151
|
| **Author** | Matt Ray (<matt@chef.io>) |
|
101
|
-
| **Copyright:** | Copyright (c) 2017 Chef Software Inc
|
152
|
+
| **Copyright:** | Copyright (c) 2017-2018 Chef Software Inc.|
|
102
153
|
| **License:** | Apache License, Version 2.0 |
|
103
154
|
|
104
155
|
Licensed under the Apache License, Version 2.0 (the "License");
|
data/inspec-iggy.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path('lib', __dir__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
|
5
|
-
require
|
5
|
+
require 'inspec-iggy/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
9
|
-
spec.version = Iggy::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
8
|
+
spec.name = 'inspec-iggy'
|
9
|
+
spec.version = InspecPlugins::Iggy::VERSION
|
10
|
+
spec.authors = ['Matt Ray']
|
11
|
+
spec.email = ['matt@chef.io']
|
12
|
+
spec.summary = 'InSpec plugin to generate InSpec compliance profiles from Terraform.'
|
13
|
+
spec.description = 'Generate InSpec compliance profiles from Terraform by tagging instances and mapping Terraform to InSpec.'
|
14
|
+
spec.homepage = 'https://github.com/inspec/inspec-iggy'
|
15
|
+
spec.license = 'Apache-2.0'
|
16
16
|
|
17
17
|
spec.files = %w{
|
18
18
|
README.md inspec-iggy.gemspec Gemfile
|
19
19
|
} + Dir.glob(
|
20
|
-
|
20
|
+
'{bin,docs,examples,lib,tasks}/**/*', File::FNM_DOTMATCH
|
21
21
|
).reject { |f| File.directory?(f) }
|
22
22
|
|
23
|
-
spec.require_paths = [
|
23
|
+
spec.require_paths = ['lib']
|
24
24
|
|
25
|
-
spec.add_dependency
|
25
|
+
spec.add_dependency 'inspec', '>=2.3', '<4.0.0'
|
26
26
|
end
|
data/lib/inspec-iggy.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# This file is known as the "entry point."
|
4
|
+
# This is the file InSpec will try to load if it
|
5
|
+
# thinks your plugin is installed.
|
6
|
+
|
7
|
+
# The *only* thing this file should do is setup the
|
8
|
+
# load path, then load the plugin definition file.
|
9
|
+
|
10
|
+
# Next two lines simply add the path of the gem to the load path.
|
11
|
+
# This is not needed when being loaded as a gem; but when doing
|
12
|
+
# plugin development, you may need it. Either way, it's harmless.
|
3
13
|
libdir = File.dirname(__FILE__)
|
4
14
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
5
15
|
|
6
|
-
require
|
7
|
-
require "inspec-iggy/version"
|
16
|
+
require 'inspec-iggy/plugin'
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Matt Ray (<matt@chef.io>)
|
4
|
+
#
|
5
|
+
# Copyright:: 2018, Chef Software, Inc <legal@chef.io>
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'inspec/plugin/v2'
|
9
|
+
|
10
|
+
require 'inspec-iggy/version'
|
11
|
+
require 'inspec-iggy/profile'
|
12
|
+
require 'inspec-iggy/cloudformation/parser'
|
13
|
+
|
14
|
+
module InspecPlugins::Iggy
|
15
|
+
module CloudFormation
|
16
|
+
class CliCommand < Inspec.plugin(2, :cli_command)
|
17
|
+
subcommand_desc 'cloudformation SUBCOMMAND ...', 'Generate InSpec from CloudFormation'
|
18
|
+
|
19
|
+
# Thor.map(Hash) allows you to make aliases for commands.
|
20
|
+
map('-v' => 'version') # Treat `inspec terraform -v`` as `inspec terraform version`
|
21
|
+
map('--version' => 'version') # Treat `inspec terraform -version`` as `inspec terraform version`
|
22
|
+
|
23
|
+
desc 'version', 'Display version information', hide: true
|
24
|
+
def version
|
25
|
+
say("Iggy v#{InspecPlugins::Iggy::VERSION}")
|
26
|
+
end
|
27
|
+
|
28
|
+
option :debug,
|
29
|
+
desc: 'Verbose debugging messages',
|
30
|
+
type: :boolean,
|
31
|
+
default: false
|
32
|
+
|
33
|
+
option :copyright,
|
34
|
+
desc: 'Name of the copyright holder',
|
35
|
+
default: 'The Authors'
|
36
|
+
|
37
|
+
option :email,
|
38
|
+
desc: 'Email address of the author',
|
39
|
+
default: 'you@example.com'
|
40
|
+
|
41
|
+
option :license,
|
42
|
+
desc: 'License for the profile',
|
43
|
+
default: 'Apache-2.0'
|
44
|
+
|
45
|
+
option :maintainer,
|
46
|
+
desc: 'Name of the copyright holder',
|
47
|
+
default: 'The Authors'
|
48
|
+
|
49
|
+
option :summary,
|
50
|
+
desc: 'One line summary for the profile',
|
51
|
+
default: 'An InSpec Compliance Profile'
|
52
|
+
|
53
|
+
option :title,
|
54
|
+
desc: 'Human-readable name for the profile',
|
55
|
+
default: 'InSpec Profile'
|
56
|
+
|
57
|
+
option :version,
|
58
|
+
desc: 'Specify the profile version',
|
59
|
+
default: '0.1.0'
|
60
|
+
|
61
|
+
option :overwrite,
|
62
|
+
desc: 'Overwrites existing profile directory',
|
63
|
+
type: :boolean,
|
64
|
+
default: false
|
65
|
+
|
66
|
+
option :name,
|
67
|
+
aliases: '-n',
|
68
|
+
required: true,
|
69
|
+
desc: 'Name of profile to be generated'
|
70
|
+
|
71
|
+
option :stack,
|
72
|
+
aliases: '-s',
|
73
|
+
required: true,
|
74
|
+
desc: 'Specify stack name or unique stack ID associated with the CloudFormation template'
|
75
|
+
|
76
|
+
option :template,
|
77
|
+
aliases: '-t',
|
78
|
+
required: true,
|
79
|
+
desc: 'Specify path to the input CloudFormation template'
|
80
|
+
|
81
|
+
desc 'generate [options]', 'Generate InSpec compliance controls from CloudFormation template'
|
82
|
+
def generate
|
83
|
+
Inspec::Log.level = :debug if options[:debug]
|
84
|
+
# hash of generated controls
|
85
|
+
generated_controls = InspecPlugins::Iggy::CloudFormation::Parser.parse_generate(options[:template])
|
86
|
+
printable_controls = InspecPlugins::Iggy::InspecHelper.cfn_controls(options[:title], generated_controls, options[:stack])
|
87
|
+
InspecPlugins::Iggy::Profile.render_profile(self, options, options[:template], printable_controls)
|
88
|
+
exit 0
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Matt Ray (<matt@chef.io>)
|
3
|
+
#
|
4
|
+
# Copyright:: 2018, Chef Software, Inc <legal@chef.io>
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'json'
|
8
|
+
require 'inspec/objects/control'
|
9
|
+
require 'inspec/objects/ruby_helper'
|
10
|
+
require 'inspec/objects/describe'
|
11
|
+
|
12
|
+
require 'inspec-iggy/inspec_helper'
|
13
|
+
|
14
|
+
module InspecPlugins::Iggy::CloudFormation
|
15
|
+
class Parser
|
16
|
+
def self.parse_generate(file) # rubocop:disable all
|
17
|
+
Inspec::Log.debug "CloudFormation.parse_generate file = #{file}"
|
18
|
+
begin
|
19
|
+
unless File.file?(file)
|
20
|
+
STDERR.puts "ERROR: #{file} is an invalid file, please check your path."
|
21
|
+
exit(-1)
|
22
|
+
end
|
23
|
+
template = JSON.parse(File.read(file))
|
24
|
+
rescue JSON::ParserError => e
|
25
|
+
STDERR.puts e.message
|
26
|
+
STDERR.puts "ERROR: Parsing error in #{file}."
|
27
|
+
exit(-1)
|
28
|
+
end
|
29
|
+
absolutename = File.absolute_path(file)
|
30
|
+
|
31
|
+
# InSpec controls generated
|
32
|
+
generated_controls = []
|
33
|
+
# iterate over the resources
|
34
|
+
cfn_resources = template['Resources']
|
35
|
+
cfn_resources.keys.each do |cfn_res|
|
36
|
+
# split out the last ::, these are all AWS
|
37
|
+
cfn_resource = cfn_resources[cfn_res]['Type'].split('::').last
|
38
|
+
# split camelcase and join with underscores
|
39
|
+
cfn_res_type = 'aws_' + cfn_resource.split(/(?=[A-Z])/).join('_').downcase
|
40
|
+
|
41
|
+
# add translation layer
|
42
|
+
if InspecPlugins::Iggy::InspecHelper::TRANSLATED_RESOURCES.key?(cfn_res_type)
|
43
|
+
Inspec::Log.debug "CloudFormation.parse_generate cfn_res_type = #{cfn_res_type} #{InspecPlugins::Iggy::InspecHelper::TRANSLATED_RESOURCES[cfn_res_type]} TRANSLATED"
|
44
|
+
cfn_res_type = InspecPlugins::Iggy::InspecHelper::TRANSLATED_RESOURCES[cfn_res_type]
|
45
|
+
end
|
46
|
+
|
47
|
+
# does this match an InSpec resource?
|
48
|
+
if InspecPlugins::Iggy::InspecHelper::RESOURCES.include?(cfn_res_type)
|
49
|
+
Inspec::Log.debug "CloudFormation.parse_generate cfn_res_type = #{cfn_res_type} MATCH"
|
50
|
+
|
51
|
+
# insert new control based off the resource's ID
|
52
|
+
ctrl = Inspec::Control.new
|
53
|
+
ctrl.id = "#{cfn_res_type}::#{cfn_res}"
|
54
|
+
ctrl.title = "InSpec-Iggy #{cfn_res_type}::#{cfn_res}"
|
55
|
+
ctrl.descriptions['default'] = "#{cfn_res_type}::#{cfn_res} from the source file #{absolutename}\nGenerated by InSpec-Iggy v#{InspecPlugins::Iggy::VERSION}"
|
56
|
+
ctrl.impact = '1.0'
|
57
|
+
|
58
|
+
describe = Inspec::Describe.new
|
59
|
+
# describes the resource with the logical_resource_id as argument, replaced at inspec exec
|
60
|
+
describe.qualifier.push([cfn_res_type, "resources[#{cfn_res}]"])
|
61
|
+
|
62
|
+
# ensure the resource exists
|
63
|
+
describe.add_test(nil, 'exist', nil)
|
64
|
+
|
65
|
+
# EC2 instances should be running
|
66
|
+
describe.add_test(nil, 'be_running', nil) if cfn_res_type.eql?('aws_ec2_instance')
|
67
|
+
|
68
|
+
# if there's a match, see if there are matching InSpec properties
|
69
|
+
inspec_properties = InspecPlugins::Iggy::InspecHelper.resource_properties(cfn_res_type)
|
70
|
+
cfn_resources[cfn_res]['Properties'].keys.each do |attr|
|
71
|
+
# insert '_' on the CamelCase to get camel_case
|
72
|
+
attr_split = attr.split(/(?=[A-Z])/)
|
73
|
+
property = attr_split.join('_').downcase
|
74
|
+
if inspec_properties.member?(property)
|
75
|
+
Inspec::Log.debug "CloudFormation.parse_generate #{cfn_res_type} inspec_property = #{property} MATCH"
|
76
|
+
value = cfn_resources[cfn_res]['Properties'][attr]
|
77
|
+
if (value.is_a? Hash) || (value.is_a? Array)
|
78
|
+
# these get replaced at inspec exec
|
79
|
+
if property.eql?('vpc_id') # rubocop:disable Metrics/BlockNesting
|
80
|
+
vpc = cfn_resources[cfn_res]['Properties'][attr].values.first
|
81
|
+
# https://github.com/inspec/inspec/issues/3173
|
82
|
+
describe.add_test(property, 'eq', "resources[#{vpc}]") unless cfn_res_type.eql?('aws_route_table') # rubocop:disable Metrics/BlockNesting
|
83
|
+
# AMI is a Ref into Parameters
|
84
|
+
elsif property.eql?('image_id') # rubocop:disable Metrics/BlockNesting
|
85
|
+
amiref = cfn_resources[cfn_res]['Properties'][attr].values.first
|
86
|
+
ami = template['Parameters'][amiref]['Default']
|
87
|
+
describe.add_test(property, 'eq', ami)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
describe.add_test(property, 'eq', value)
|
91
|
+
end
|
92
|
+
else
|
93
|
+
Inspec::Log.debug "CloudFormation.parse_generate #{cfn_res_type} inspec_property = #{property} SKIP"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
ctrl.add_test(describe)
|
97
|
+
generated_controls.push(ctrl)
|
98
|
+
else
|
99
|
+
Inspec::Log.debug "CloudFormation.parse_generate cfn_res_type = #{cfn_res_type} SKIP"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
Inspec::Log.debug "CloudFormation.parse_generate generated_controls = #{generated_controls}"
|
103
|
+
generated_controls
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|