terracop 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +20 -1
- data/README.md +6 -5
- data/lib/terracop.rb +6 -1
- data/lib/terracop/cop/aws/bad_password_policy.rb +73 -0
- data/lib/terracop/cop/aws/ensure_propagated_tags.rb +60 -0
- data/lib/terracop/cop/aws/ensure_tags.rb +23 -5
- data/lib/terracop/cop/aws/fault_intolerant.rb +40 -0
- data/lib/terracop/cop/aws/{iam_role_policy.rb → iam_inline_policy.rb} +7 -5
- data/lib/terracop/cop/aws/iam_policy_attachment.rb +48 -0
- data/lib/terracop/cop/aws/prefer_launch_templates.rb +41 -0
- data/lib/terracop/plan_loader.rb +4 -1
- data/lib/terracop/runner.rb +25 -16
- data/lib/terracop/version.rb +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fb344f85daa3aa3f6d3c3c4f0d436c0b4c0d4211e4fbc6ff3b19f44e1ea1148
|
4
|
+
data.tar.gz: 2bbff8adc3eeeedf696296e9ce90c4cbebe2ced06c781fe703f14477f8a58f93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b695431e3b74dd944dc60f5df9fb70ac88c9884c2a51397ef1ad59539359efabdfdd767302faf2be925d31e61cc2540558deea6e5870029287a424fc7607ac7
|
7
|
+
data.tar.gz: a5b1ef53d62e241551a38aaab925df92c3811355fd42a66075e56247d78c43f3162b356a06125b8d03a176538d1ba270cc652a4c3715f9837e0cb56b645b1e3f
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,7 +4,26 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
-
## 0.
|
7
|
+
## 0.2.0 (2019-12-28)
|
8
|
+
|
9
|
+
- New cops:
|
10
|
+
- Aws/BadPasswordPolicy
|
11
|
+
- Aws/EnsurePropagatedTags
|
12
|
+
- Aws/FaultIntolerant
|
13
|
+
- Aws/IamInlinePolicy
|
14
|
+
- Aws/IamPolicyAttachment
|
15
|
+
- Aws/PreferLaunchTemplates
|
16
|
+
- Deprecated cop: IamRolePolicy.
|
17
|
+
- Improve test coverage.
|
18
|
+
- Improve Aws/EnsureTags to handle weird resources.
|
19
|
+
- Ignore deletions when analyzing plans.
|
20
|
+
|
21
|
+
## 0.1.1 (2019-12-22)
|
22
|
+
|
23
|
+
- Exit with failure when offenses are found.
|
24
|
+
- Add `terracop` executable.
|
25
|
+
|
26
|
+
## 0.1.0 (2019-12-22)
|
8
27
|
|
9
28
|
- Initial release.
|
10
29
|
- Can load Terraform 0.12 state and plan files.
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Terracop
|
2
2
|
|
3
|
-
Terracop is
|
4
|
-
parser and analyzer. Put it in a CI pipeline to analyze your
|
5
|
-
or run it on already applied states and see what could be
|
3
|
+
Terracop is an opinionated HashiCorp [Terraform](https://www.terraform.io/)
|
4
|
+
state / plan parser and analyzer. Put it in a CI pipeline to analyze your
|
5
|
+
Terraform plans or run it on already applied states and see what could be
|
6
|
+
improved.
|
6
7
|
|
7
8
|
The checks run by Terracop go anywhere from resource names guidelines to
|
8
9
|
identifying security holes in your configuration.
|
@@ -33,8 +34,8 @@ like this:
|
|
33
34
|
|
34
35
|
$ terracop --state path/to/state/file
|
35
36
|
|
36
|
-
Terracop can
|
37
|
-
|
37
|
+
Terracop can also parse terraform plan files, in order to report potential
|
38
|
+
issues before you apply the plan and persist the problem. Eg:
|
38
39
|
|
39
40
|
$ terraform plan -out tfplan
|
40
41
|
$ terracop --plan tfplan
|
data/lib/terracop.rb
CHANGED
@@ -3,12 +3,17 @@
|
|
3
3
|
require 'json'
|
4
4
|
require 'yaml'
|
5
5
|
|
6
|
+
require 'terracop/cop/aws/bad_password_policy'
|
6
7
|
require 'terracop/cop/aws/describe_security_group_rules'
|
8
|
+
require 'terracop/cop/aws/ensure_propagated_tags'
|
7
9
|
require 'terracop/cop/aws/ensure_tags'
|
8
|
-
require 'terracop/cop/aws/
|
10
|
+
require 'terracop/cop/aws/fault_intolerant'
|
11
|
+
require 'terracop/cop/aws/iam_inline_policy'
|
12
|
+
require 'terracop/cop/aws/iam_policy_attachment'
|
9
13
|
require 'terracop/cop/aws/open_egress'
|
10
14
|
require 'terracop/cop/aws/open_ingress'
|
11
15
|
require 'terracop/cop/aws/open_ssh'
|
16
|
+
require 'terracop/cop/aws/prefer_launch_templates'
|
12
17
|
require 'terracop/cop/aws/unrestricted_egress_ports'
|
13
18
|
require 'terracop/cop/aws/unrestricted_ingress_ports'
|
14
19
|
require 'terracop/cop/aws/wide_egress'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'terracop/cop/base'
|
4
|
+
|
5
|
+
module Terracop
|
6
|
+
module Cop
|
7
|
+
module Aws
|
8
|
+
# This cop warns against a password policy that goes against industry
|
9
|
+
# best practices. Ideally the password policy should be strict enough
|
10
|
+
# to require the use of a password manager, and never expire passwords.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # bad
|
14
|
+
# resource "aws_iam_account_password_policy" "policy" {
|
15
|
+
# minimum_password_length = 4
|
16
|
+
# require_lowercase_characters = true
|
17
|
+
# require_numbers = true
|
18
|
+
# allow_users_to_change_password = false
|
19
|
+
# max_password_age = 7
|
20
|
+
# }
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# resource "aws_iam_account_password_policy" "policy" {
|
24
|
+
# minimum_password_length = 20
|
25
|
+
# require_lowercase_characters = true
|
26
|
+
# require_uppercase_characters = true
|
27
|
+
# require_numbers = true
|
28
|
+
# require_symbols = true
|
29
|
+
# allow_users_to_change_password = true
|
30
|
+
# }
|
31
|
+
class BadPasswordPolicy < Base
|
32
|
+
register
|
33
|
+
applies_to :aws_iam_account_password_policy
|
34
|
+
|
35
|
+
def check
|
36
|
+
check_length
|
37
|
+
check_characters
|
38
|
+
check_age
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_length
|
42
|
+
length = attributes['minimum_password_length']
|
43
|
+
if length && length < 14
|
44
|
+
offense('Set the minimum password length policy to at least 14.')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_characters
|
49
|
+
if !attributes['require_uppercase_characters'] ||
|
50
|
+
!attributes['require_lowercase_characters']
|
51
|
+
offense('Require both lowercase and uppercase characters.')
|
52
|
+
end
|
53
|
+
|
54
|
+
unless attributes['require_numbers']
|
55
|
+
offense('Require numbers in passwords.')
|
56
|
+
end
|
57
|
+
|
58
|
+
unless attributes['require_symbols']
|
59
|
+
offense('Require symbols in passwords.')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_age
|
64
|
+
age = attributes['max_password_age']
|
65
|
+
if age && age < 90
|
66
|
+
offense('Expiring passwords is discouraged. If you really have ' \
|
67
|
+
'to, do not do it more than once every 3 months.')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'terracop/cop/base'
|
4
|
+
|
5
|
+
module Terracop
|
6
|
+
module Cop
|
7
|
+
module Aws
|
8
|
+
# This cop makes sure that EC2 instances launched by Autoscaling Groups
|
9
|
+
# also have tags. It is configured like the Aws/EnsureTags cop.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# resource "aws_asg" "asg" {
|
14
|
+
# tag {
|
15
|
+
# key = "Name"
|
16
|
+
# value = "asg"
|
17
|
+
# propagate_at_launch = false
|
18
|
+
# }
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# resource "aws_asg" "asg" {
|
23
|
+
# tag {
|
24
|
+
# key = "Name"
|
25
|
+
# value = "asg"
|
26
|
+
# propagate_at_launch = true
|
27
|
+
# }
|
28
|
+
# }
|
29
|
+
class EnsurePropagatedTags < Base
|
30
|
+
register
|
31
|
+
applies_to :aws_autoscaling_group
|
32
|
+
|
33
|
+
def check
|
34
|
+
if self.class.config['Required']
|
35
|
+
check_required(propagated_tags, self.class.config['Required'])
|
36
|
+
elsif propagated_tags.empty?
|
37
|
+
offense 'The EC2 instances launched by this Autoscaling group ' \
|
38
|
+
'will not have any tags.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def propagated_tags
|
45
|
+
tags = attributes['tags'] || attributes['tag']
|
46
|
+
tags.select { |t| t['propagate_at_launch'] }
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_required(tags, required_tags)
|
50
|
+
required_tags.each do |key|
|
51
|
+
unless tags.find { |t| t['key'] == key }
|
52
|
+
offense "Required tag \"#{key}\" is not propagated to EC2 " \
|
53
|
+
'instances launched by this Autoscaling Group.'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -27,24 +27,42 @@ module Terracop
|
|
27
27
|
register
|
28
28
|
|
29
29
|
def check
|
30
|
-
|
30
|
+
tags = tags_for(attributes)
|
31
|
+
return unless tags
|
31
32
|
|
32
33
|
if self.class.config['Required']
|
33
|
-
check_required(self.class.config['Required'])
|
34
|
-
elsif
|
34
|
+
check_required(tags, self.class.config['Required'])
|
35
|
+
elsif tags.empty?
|
35
36
|
offense 'Tag resources properly.'
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
39
40
|
private
|
40
41
|
|
41
|
-
def check_required(required_tags)
|
42
|
+
def check_required(tags, required_tags)
|
42
43
|
required_tags.each do |key|
|
43
|
-
unless
|
44
|
+
unless tag(tags, key)
|
44
45
|
offense "Required tag \"#{key}\" is missing on this resource."
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
49
|
+
|
50
|
+
def tags_for(attributes)
|
51
|
+
case type
|
52
|
+
when 'aws_autoscaling_group'
|
53
|
+
attributes['tags'] || attributes['tag']
|
54
|
+
else
|
55
|
+
attributes['tags']
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def tag(list, name)
|
60
|
+
if list.is_a?(Hash)
|
61
|
+
list[name]
|
62
|
+
else
|
63
|
+
list.find { |tag| tag['key'] == name }
|
64
|
+
end
|
65
|
+
end
|
48
66
|
end
|
49
67
|
end
|
50
68
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'terracop/cop/base'
|
4
|
+
|
5
|
+
module Terracop
|
6
|
+
module Cop
|
7
|
+
module Aws
|
8
|
+
# This cop checks for Autoscaling Groups that can only launch instances
|
9
|
+
# in a specific Availability Zone. This creates an availability risk,
|
10
|
+
# as if that AZ is lost, the ASG will not be able to launch instances
|
11
|
+
# anywhere else.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# resource "aws_autoscaling_group" "asg" {
|
16
|
+
# vpc_zone_identifier = ["subnet-123"]
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# resource "aws_autoscaling_group" "asg" {
|
21
|
+
# # Note that to pass this cop, the two subnets must live in
|
22
|
+
# # different AZs.
|
23
|
+
# vpc_zone_identifier = ["subnet-123", "subnet-456"]
|
24
|
+
# }
|
25
|
+
class FaultIntolerant < Base
|
26
|
+
register
|
27
|
+
applies_to :aws_autoscaling_group
|
28
|
+
|
29
|
+
MSG = 'This Autoscaling Group can launch instances in only one AZ ' \
|
30
|
+
'(%<az>s). This setup would not tolerate the loss of that AZ.'
|
31
|
+
|
32
|
+
def check
|
33
|
+
return unless attributes['availability_zones'].count < 2
|
34
|
+
|
35
|
+
offense(format(MSG, az: attributes['availability_zones'][0]))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -5,7 +5,7 @@ require 'terracop/cop/base'
|
|
5
5
|
module Terracop
|
6
6
|
module Cop
|
7
7
|
module Aws
|
8
|
-
# This cop warns against the use of inline role policies.
|
8
|
+
# This cop warns against the use of inline group/role/user policies.
|
9
9
|
# Inline policies tend to be copy/pasted, sometimes with minor changes
|
10
10
|
# and are not shown in the "Policies" tab of AWS IAM.
|
11
11
|
#
|
@@ -33,13 +33,15 @@ module Terracop
|
|
33
33
|
# role = aws_iam_role.role.name
|
34
34
|
# policy_arn = aws_iam_policy.policy.arn
|
35
35
|
# }
|
36
|
-
class
|
36
|
+
class IamInlinePolicy < Base
|
37
37
|
register
|
38
|
-
applies_to :aws_iam_role_policy
|
38
|
+
applies_to :aws_iam_group_policy, :aws_iam_role_policy,
|
39
|
+
:aws_iam_user_policy
|
39
40
|
|
40
41
|
def check
|
41
|
-
|
42
|
-
|
42
|
+
entity = type.scan(/aws_iam_(.+)_policy/).first.first
|
43
|
+
offense("Use aws_iam_#{entity}_policy_attachment instead of " \
|
44
|
+
"attaching inline policies with aws_iam_#{entity}_policy.")
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'terracop/cop/base'
|
4
|
+
|
5
|
+
module Terracop
|
6
|
+
module Cop
|
7
|
+
module Aws
|
8
|
+
# This cop warns against the use of an evil all encompassing
|
9
|
+
# aws_iam_policy_attachment.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# resource "aws_iam_policy_attachment" "attach" {
|
14
|
+
# name = "test-attachment"
|
15
|
+
# policy_arn = aws_iam_policy.policy.arn
|
16
|
+
# users = [aws_iam_user.user.name]
|
17
|
+
# roles = [aws_iam_role.role.name]
|
18
|
+
# groups = [aws_iam_group.group.name]
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# resource "aws_iam_role_policy_attachment" "attach" {
|
23
|
+
# role = aws_iam_role.role.name
|
24
|
+
# policy_arn = aws_iam_policy.policy.arn
|
25
|
+
# }
|
26
|
+
#
|
27
|
+
# resource "aws_iam_user_policy_attachment" "attach" {
|
28
|
+
# user = aws_iam_user.user.name
|
29
|
+
# policy_arn = aws_iam_policy.policy.arn
|
30
|
+
# }
|
31
|
+
#
|
32
|
+
# resource "aws_iam_group_policy_attachment" "attach" {
|
33
|
+
# group = aws_iam_group.user.name
|
34
|
+
# policy_arn = aws_iam_policy.policy.arn
|
35
|
+
# }
|
36
|
+
class IamPolicyAttachment < Base
|
37
|
+
register
|
38
|
+
applies_to :iam_policy_attachment
|
39
|
+
|
40
|
+
def check
|
41
|
+
offense('Use aws_iam_role_policy_attachment, ' \
|
42
|
+
'aws_iam_user_policy_attachment, or ' \
|
43
|
+
'aws_iam_group_policy_attachment instead.')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'terracop/cop/aws/security_group_rule_cop'
|
4
|
+
|
5
|
+
module Terracop
|
6
|
+
module Cop
|
7
|
+
module Aws
|
8
|
+
# This cop warns against an ingress rule from 0.0.0.0/0 on port 22 (SSH).
|
9
|
+
# That is a Very Bad Idea™.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# resource "aws_launch_configuration" "lc" {}
|
14
|
+
#
|
15
|
+
# resource "aws_autoscaling_group" "asg" {
|
16
|
+
# launch_configuration = aws_launch_configuration.lc.name
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# resource "aws_launch_template" "tpl" {}
|
21
|
+
#
|
22
|
+
# resource "aws_autoscaling_group" "asg" {
|
23
|
+
# launch_template {
|
24
|
+
# id = aws_launch_template.tpl.id
|
25
|
+
# version = "$Latest"
|
26
|
+
# }
|
27
|
+
# }
|
28
|
+
class PreferLaunchTemplates < SecurityGroupRuleCop
|
29
|
+
register
|
30
|
+
applies_to :aws_launch_configuration, :aws_autoscaling_group
|
31
|
+
|
32
|
+
def check
|
33
|
+
if type == 'aws_launch_configuration' ||
|
34
|
+
attributes['launch_configuration']
|
35
|
+
offense('Prefer Launch Templates to Launch Configurations.')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/terracop/plan_loader.rb
CHANGED
@@ -9,7 +9,8 @@ module Terracop
|
|
9
9
|
plan = decode(file)
|
10
10
|
|
11
11
|
changed_resources = plan['resource_changes'].reject! do |resource|
|
12
|
-
resource['change']['actions'] == ['no-op']
|
12
|
+
resource['change']['actions'] == ['no-op'] ||
|
13
|
+
resource['change']['actions'] == ['delete']
|
13
14
|
end
|
14
15
|
|
15
16
|
restruct_resources(changed_resources)
|
@@ -17,12 +18,14 @@ module Terracop
|
|
17
18
|
|
18
19
|
private
|
19
20
|
|
21
|
+
# :nocov:
|
20
22
|
def decode(file)
|
21
23
|
JSON.parse(`terraform show -json #{file}`)
|
22
24
|
rescue JSON::ParserError
|
23
25
|
puts 'Terraform failed to decode the plan file.'
|
24
26
|
exit
|
25
27
|
end
|
28
|
+
# :nocov:
|
26
29
|
|
27
30
|
def restruct_resources(resources)
|
28
31
|
resources.map do |resource|
|
data/lib/terracop/runner.rb
CHANGED
@@ -3,50 +3,59 @@
|
|
3
3
|
module Terracop
|
4
4
|
# Executes Terracop on a given state file.
|
5
5
|
class Runner
|
6
|
-
attr_accessor :state
|
7
|
-
|
8
6
|
def initialize(type, file, formatter)
|
9
7
|
@formatter = Formatters.const_get(formatter.to_s.capitalize).new
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
else
|
14
|
-
load_state_from_terraform
|
15
|
-
end
|
9
|
+
@type = type
|
10
|
+
@file = file
|
16
11
|
end
|
17
12
|
|
18
13
|
def run
|
19
|
-
offenses =
|
14
|
+
offenses = state.map do |instance|
|
20
15
|
Terracop::Cop.run_for(
|
21
16
|
instance[:type], instance[:name],
|
22
17
|
instance[:index], instance[:attributes]
|
23
18
|
)
|
24
19
|
end
|
25
20
|
|
26
|
-
|
27
|
-
print @formatter.generate(by_res)
|
21
|
+
print formatted(offenses)
|
28
22
|
|
29
23
|
offenses.flatten.count
|
30
24
|
end
|
31
25
|
|
26
|
+
def state
|
27
|
+
@state ||= begin
|
28
|
+
if @file
|
29
|
+
load_state_from_file(@type, @file)
|
30
|
+
else
|
31
|
+
load_state_from_terraform
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
32
36
|
private
|
33
37
|
|
34
38
|
def load_state_from_file(type, file)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
if type == :plan
|
40
|
+
PlanLoader.load(file)
|
41
|
+
else
|
42
|
+
StateLoader.load(file)
|
43
|
+
end
|
40
44
|
end
|
41
45
|
|
42
46
|
# :nocov:
|
43
47
|
def load_state_from_terraform
|
44
|
-
|
48
|
+
StateLoader.load_from_text(`terraform state pull`)
|
45
49
|
rescue JSON::ParserError
|
46
50
|
puts 'Run terracop somewhere with a state file or pass it directly ' \
|
47
51
|
'with --state FILE'
|
48
52
|
exit
|
49
53
|
end
|
50
54
|
# :nocov:
|
55
|
+
|
56
|
+
def formatted(offenses)
|
57
|
+
by_res = offenses.flatten.group_by { |o| "#{o[:type]}.#{o[:name]}" }
|
58
|
+
@formatter.generate(by_res)
|
59
|
+
end
|
51
60
|
end
|
52
61
|
end
|
data/lib/terracop/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terracop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francesco Boffa
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -148,12 +148,17 @@ files:
|
|
148
148
|
- default_config.yml
|
149
149
|
- exe/terracop
|
150
150
|
- lib/terracop.rb
|
151
|
+
- lib/terracop/cop/aws/bad_password_policy.rb
|
151
152
|
- lib/terracop/cop/aws/describe_security_group_rules.rb
|
153
|
+
- lib/terracop/cop/aws/ensure_propagated_tags.rb
|
152
154
|
- lib/terracop/cop/aws/ensure_tags.rb
|
153
|
-
- lib/terracop/cop/aws/
|
155
|
+
- lib/terracop/cop/aws/fault_intolerant.rb
|
156
|
+
- lib/terracop/cop/aws/iam_inline_policy.rb
|
157
|
+
- lib/terracop/cop/aws/iam_policy_attachment.rb
|
154
158
|
- lib/terracop/cop/aws/open_egress.rb
|
155
159
|
- lib/terracop/cop/aws/open_ingress.rb
|
156
160
|
- lib/terracop/cop/aws/open_ssh.rb
|
161
|
+
- lib/terracop/cop/aws/prefer_launch_templates.rb
|
157
162
|
- lib/terracop/cop/aws/security_group_rule_cop.rb
|
158
163
|
- lib/terracop/cop/aws/unrestricted_egress_ports.rb
|
159
164
|
- lib/terracop/cop/aws/unrestricted_ingress_ports.rb
|
@@ -194,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
199
|
- !ruby/object:Gem::Version
|
195
200
|
version: '0'
|
196
201
|
requirements: []
|
197
|
-
rubygems_version: 3.
|
202
|
+
rubygems_version: 3.1.2
|
198
203
|
signing_key:
|
199
204
|
specification_version: 4
|
200
205
|
summary: Automatic Terraform state/plan checking tool
|