cfn-model 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/cfn_parse +8 -0
- data/lib/cfn-model/model/bucket_policy.rb +13 -0
- data/lib/cfn-model/model/cfn_model.rb +64 -0
- data/lib/cfn-model/model/ec2_instance.rb +15 -0
- data/lib/cfn-model/model/ec2_network_interface.rb +18 -0
- data/lib/cfn-model/model/iam_group.rb +15 -0
- data/lib/cfn-model/model/iam_managed_policy.rb +14 -0
- data/lib/cfn-model/model/iam_policy.rb +14 -0
- data/lib/cfn-model/model/iam_role.rb +14 -0
- data/lib/cfn-model/model/iam_user.rb +16 -0
- data/lib/cfn-model/model/iam_user_to_group_addition.rb +10 -0
- data/lib/cfn-model/model/load_balancer.rb +37 -0
- data/lib/cfn-model/model/model_element.rb +101 -0
- data/lib/cfn-model/model/policy.rb +10 -0
- data/lib/cfn-model/model/policy_document.rb +52 -0
- data/lib/cfn-model/model/principal.rb +34 -0
- data/lib/cfn-model/model/queue_policy.rb +13 -0
- data/lib/cfn-model/model/references.rb +52 -0
- data/lib/cfn-model/model/security_group.rb +18 -0
- data/lib/cfn-model/model/security_group_egress.rb +29 -0
- data/lib/cfn-model/model/security_group_ingress.rb +38 -0
- data/lib/cfn-model/model/statement.rb +38 -0
- data/lib/cfn-model/model/topic_policy.rb +13 -0
- data/lib/cfn-model/parser/cfn_parser.rb +126 -0
- data/lib/cfn-model/parser/ec2_instance_parser.rb +10 -0
- data/lib/cfn-model/parser/ec2_network_interface_parser.rb +10 -0
- data/lib/cfn-model/parser/iam_group_parser.rb +17 -0
- data/lib/cfn-model/parser/iam_role_parser.rb +20 -0
- data/lib/cfn-model/parser/iam_user_parser.rb +58 -0
- data/lib/cfn-model/parser/load_balancer_parser.rb +10 -0
- data/lib/cfn-model/parser/load_balancer_v2_parser.rb +15 -0
- data/lib/cfn-model/parser/parser_error.rb +13 -0
- data/lib/cfn-model/parser/parser_registry.rb +34 -0
- data/lib/cfn-model/parser/policy_document_parser.rb +44 -0
- data/lib/cfn-model/parser/security_group_parser.rb +83 -0
- data/lib/cfn-model/parser/with_policy_document_parser.rb +10 -0
- data/lib/cfn-model/schema/AWS_CloudFront_Distribution.yml +42 -0
- data/lib/cfn-model/schema/AWS_EC2_Instance.yml +146 -0
- data/lib/cfn-model/schema/AWS_EC2_NetworkInterface.yml +62 -0
- data/lib/cfn-model/schema/AWS_EC2_NetworkInterfaceAttachment.yml +24 -0
- data/lib/cfn-model/schema/AWS_EC2_SecurityGroup.yml +71 -0
- data/lib/cfn-model/schema/AWS_EC2_SecurityGroupEgress.yml +27 -0
- data/lib/cfn-model/schema/AWS_EC2_SecurityGroupIngress.yml +27 -0
- data/lib/cfn-model/schema/AWS_ElasticLoadBalancingV2_LoadBalancer.yml +56 -0
- data/lib/cfn-model/schema/AWS_ElasticLoadBalancing_LoadBalancer.yml +188 -0
- data/lib/cfn-model/schema/AWS_IAM_Group.yml +23 -0
- data/lib/cfn-model/schema/AWS_IAM_ManagedPolicy.yml +34 -0
- data/lib/cfn-model/schema/AWS_IAM_Policy.yml +36 -0
- data/lib/cfn-model/schema/AWS_IAM_Role.yml +28 -0
- data/lib/cfn-model/schema/AWS_IAM_User.yml +38 -0
- data/lib/cfn-model/schema/AWS_IAM_UserToGroupAddition.yml +23 -0
- data/lib/cfn-model/schema/AWS_Lambda_Permission.yml +24 -0
- data/lib/cfn-model/schema/AWS_S3_BucketPolicy.yml +21 -0
- data/lib/cfn-model/schema/AWS_SNS_TopicPolicy.yml +23 -0
- data/lib/cfn-model/schema/AWS_SQS_QueuePolicy.yml +23 -0
- data/lib/cfn-model/schema/schema.yml.erb +17 -0
- data/lib/cfn-model/validator/cloudformation_validator.rb +12 -0
- data/lib/cfn-model/validator/reference_validator.rb +83 -0
- data/lib/cfn-model/validator/resource_type_validator.rb +34 -0
- data/lib/cfn-model/validator/schema_generator.rb +86 -0
- data/lib/cfn-model.rb +2 -0
- metadata +120 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'cfn-model/validator/cloudformation_validator'
|
3
|
+
require 'cfn-model/validator/reference_validator'
|
4
|
+
require_relative 'parser_registry'
|
5
|
+
require_relative 'parser_error'
|
6
|
+
Dir["#{__dir__}/../model/*.rb"].each { |model| require "cfn-model/model/#{File.basename(model, '.rb')}" }
|
7
|
+
|
8
|
+
##
|
9
|
+
# This class is the heart of the matter. It will take a CloudFormation template
|
10
|
+
# and return a CfnModel object to represent the underlying document in a way
|
11
|
+
# that is hopefully more convenient for (cfn-nag rule) developers to work with
|
12
|
+
#
|
13
|
+
class CfnParser
|
14
|
+
# this will convert any !Ref or !GetAtt into tranditional hash like in json
|
15
|
+
YAML.add_domain_type('', 'Ref') { |type, val| { 'Ref' => val } }
|
16
|
+
|
17
|
+
%w(GetAtt Join Base64 Sub Split Select ImportValue GetAZs FindInMap And Or If Not).each do |function_name|
|
18
|
+
YAML.add_domain_type('', function_name) { |type, val| { "Fn::#{function_name}" => val } }
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Given raw json/yml CloudFormation template, returns a CfnModel object
|
23
|
+
# or raise ParserErrors if something is amiss with the format
|
24
|
+
def parse(cloudformation_yml)
|
25
|
+
cfn_hash = pre_validate_model cloudformation_yml
|
26
|
+
|
27
|
+
cfn_model = CfnModel.new
|
28
|
+
cfn_model.raw_model = cfn_hash
|
29
|
+
|
30
|
+
# pass 1: wire properties into ModelElement objects
|
31
|
+
transform_hash_into_model_elements cfn_hash, cfn_model
|
32
|
+
|
33
|
+
# pass 2: tie together separate resources only where necessary to make life easier for rule logic
|
34
|
+
post_process_resource_model_elements cfn_model
|
35
|
+
|
36
|
+
cfn_model
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def post_process_resource_model_elements(cfn_model)
|
42
|
+
cfn_model.resources.each do |_, resource|
|
43
|
+
resource_parser_class = ParserRegistry.instance.registry[resource.class.to_s]
|
44
|
+
|
45
|
+
next if resource_parser_class.nil?
|
46
|
+
|
47
|
+
resource_parser = resource_parser_class.new
|
48
|
+
resource_parser.parse(cfn_model: cfn_model,
|
49
|
+
resource: resource)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# pass 0: validate basic syntax so we can make some assumptions down stream
|
54
|
+
# even within the parsing code
|
55
|
+
def transform_hash_into_model_elements(cfn_hash, cfn_model)
|
56
|
+
cfn_hash['Resources'].each do |resource_name, resource|
|
57
|
+
resource_class = class_from_type_name resource['Type']
|
58
|
+
|
59
|
+
resource_object = resource_class.new
|
60
|
+
resource_object.logical_resource_id = resource_name
|
61
|
+
resource_object.resource_type = resource['Type']
|
62
|
+
|
63
|
+
assign_fields_based_upon_properties resource_object, resource
|
64
|
+
|
65
|
+
cfn_model.resources[resource_name] = resource_object
|
66
|
+
end
|
67
|
+
cfn_model
|
68
|
+
end
|
69
|
+
|
70
|
+
def pre_validate_model(cloudformation_yml)
|
71
|
+
errors = CloudFormationValidator.new.validate cloudformation_yml
|
72
|
+
if !errors.nil? && !errors.empty?
|
73
|
+
raise ParserError.new('Basic CloudFormation syntax error', errors)
|
74
|
+
end
|
75
|
+
|
76
|
+
cfn_hash = YAML.load cloudformation_yml
|
77
|
+
|
78
|
+
unresolved_refs = ReferenceValidator.new.unresolved_references(cfn_hash)
|
79
|
+
unless unresolved_refs.empty?
|
80
|
+
raise ParserError.new("Unresolved logical resource ids: #{unresolved_refs.to_a}")
|
81
|
+
end
|
82
|
+
cfn_hash
|
83
|
+
end
|
84
|
+
|
85
|
+
def assign_fields_based_upon_properties(resource_object, resource)
|
86
|
+
unless resource['Properties'].nil?
|
87
|
+
resource['Properties'].each do |property_name, property_value|
|
88
|
+
resource_object.send("#{initial_lower(property_name)}=", property_value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def class_from_type_name(type_name)
|
94
|
+
begin
|
95
|
+
resource_class = Object.const_get type_name, inherit=false
|
96
|
+
rescue NameError
|
97
|
+
# puts "Never seen class: #{type_name} so going dynamic"
|
98
|
+
resource_class = generate_resource_class_from_type type_name
|
99
|
+
end
|
100
|
+
resource_class
|
101
|
+
end
|
102
|
+
|
103
|
+
def initial_lower(str)
|
104
|
+
str.slice(0).downcase + str[1..(str.length)]
|
105
|
+
end
|
106
|
+
|
107
|
+
def generate_resource_class_from_type(type_name)
|
108
|
+
resource_class = Class.new(ModelElement)
|
109
|
+
|
110
|
+
module_names = type_name.split('::')
|
111
|
+
if module_names.first == 'Custom'
|
112
|
+
Object.const_set(module_names[1], resource_class)
|
113
|
+
elsif module_names.first == 'AWS'
|
114
|
+
begin
|
115
|
+
module_constant = AWS.const_get(module_names[1])
|
116
|
+
rescue NameError
|
117
|
+
module_constant = Module.new
|
118
|
+
module_constant.const_set(module_names[1], module_constant)
|
119
|
+
end
|
120
|
+
module_constant.const_set(module_names[2], resource_class)
|
121
|
+
else
|
122
|
+
raise "Unknown namespace in resource type: #{module_names.first}"
|
123
|
+
end
|
124
|
+
resource_class
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Ec2InstanceParser
|
2
|
+
def parse(cfn_model:, resource:)
|
3
|
+
ec2_instance = resource
|
4
|
+
|
5
|
+
ec2_instance.security_groups = ec2_instance.securityGroupIds.map do |security_group_reference|
|
6
|
+
cfn_model.find_security_group_by_group_id(security_group_reference)
|
7
|
+
end
|
8
|
+
ec2_instance
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Ec2NetworkInterfaceParser
|
2
|
+
def parse(cfn_model:, resource:)
|
3
|
+
network_interface = resource
|
4
|
+
|
5
|
+
network_interface.security_groups = network_interface.groupSet.map do |security_group_reference|
|
6
|
+
cfn_model.find_security_group_by_group_id(security_group_reference)
|
7
|
+
end
|
8
|
+
network_interface
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'cfn-model/model/iam_role'
|
2
|
+
require 'cfn-model/model/policy'
|
3
|
+
require_relative 'policy_document_parser'
|
4
|
+
|
5
|
+
class IamGroupParser
|
6
|
+
def parse(cfn_model:, resource:)
|
7
|
+
iam_group = resource
|
8
|
+
|
9
|
+
iam_group.policy_objects = iam_group.policies.map do |policy|
|
10
|
+
new_policy = Policy.new
|
11
|
+
new_policy.policyName = policy['PolicyName']
|
12
|
+
new_policy.policyDocument = PolicyDocumentParser.new.parse(policy['PolicyDocument'])
|
13
|
+
new_policy
|
14
|
+
end
|
15
|
+
iam_group
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cfn-model/model/iam_role'
|
2
|
+
require 'cfn-model/model/policy'
|
3
|
+
require_relative 'policy_document_parser'
|
4
|
+
|
5
|
+
class IamRoleParser
|
6
|
+
def parse(cfn_model:, resource:)
|
7
|
+
iam_role = resource
|
8
|
+
|
9
|
+
iam_role.assume_role_policy_document = PolicyDocumentParser.new.parse(iam_role.assumeRolePolicyDocument)
|
10
|
+
|
11
|
+
iam_role.policy_objects = iam_role.policies.map do |policy|
|
12
|
+
new_policy = Policy.new
|
13
|
+
new_policy.policy_name = policy['PolicyName']
|
14
|
+
new_policy.policy_document = PolicyDocumentParser.new.parse(policy['PolicyDocument'])
|
15
|
+
new_policy
|
16
|
+
end
|
17
|
+
|
18
|
+
iam_role
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'cfn-model/model/policy_document'
|
2
|
+
require 'cfn-model/model/policy'
|
3
|
+
require_relative 'policy_document_parser'
|
4
|
+
|
5
|
+
class IamUserParser
|
6
|
+
def parse(cfn_model:, resource:)
|
7
|
+
iam_user = resource
|
8
|
+
|
9
|
+
iam_user.policy_objects = iam_user.policies.map do |policy|
|
10
|
+
new_policy = Policy.new
|
11
|
+
new_policy.policy_name = policy['PolicyName']
|
12
|
+
new_policy.policy_document = PolicyDocumentParser.new.parse(policy['PolicyDocument'])
|
13
|
+
new_policy
|
14
|
+
end
|
15
|
+
|
16
|
+
iam_user.groups.each { |group_name| iam_user.group_names << group_name }
|
17
|
+
|
18
|
+
user_to_group_additions = cfn_model.resources_by_type 'AWS::IAM::UserToGroupAddition'
|
19
|
+
user_to_group_additions.each do |user_to_group_addition|
|
20
|
+
|
21
|
+
if user_to_group_addition_has_username(user_to_group_addition.users,iam_user)
|
22
|
+
iam_user.group_names << user_to_group_addition.groupName
|
23
|
+
|
24
|
+
# we need to figure out the story on resolving Refs i think for this to be real
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def user_to_group_addition_has_username(addition_user_names, user_to_find)
|
32
|
+
addition_user_names.each do |addition_user_name|
|
33
|
+
if addition_user_name == user_to_find.userName
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
|
37
|
+
if addition_user_name.is_a? Hash
|
38
|
+
if !addition_user_name['Ref'].nil?
|
39
|
+
if addition_user_name['Ref'] == user_to_find.logical_resource_id
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
# def resolve_user_logical_resource_id(user)
|
49
|
+
# if not user['Ref'].nil?
|
50
|
+
# user['Ref']
|
51
|
+
# elsif not user['Fn::GetAtt'].nil?
|
52
|
+
# fail 'Arn not legal for user to group addition'
|
53
|
+
# else
|
54
|
+
# @dangler
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class LoadBalancerParser
|
2
|
+
def parse(cfn_model:, resource:)
|
3
|
+
load_balancer = resource
|
4
|
+
|
5
|
+
load_balancer.security_groups = load_balancer.securityGroups.map do |security_group_reference|
|
6
|
+
cfn_model.find_security_group_by_group_id(security_group_reference)
|
7
|
+
end
|
8
|
+
load_balancer
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class LoadBalancerV2Parser
|
2
|
+
def parse(cfn_model:, resource:)
|
3
|
+
load_balancer = resource
|
4
|
+
|
5
|
+
#could be a List<Subnet::Id>
|
6
|
+
# if load_balancer.subnets.size < 2
|
7
|
+
# raise ParserError.new("Load Balancer must have at least two subnets: #{load_balancer.logical_resource_id}")
|
8
|
+
# end
|
9
|
+
|
10
|
+
load_balancer.security_groups = load_balancer.securityGroups.map do |security_group_reference|
|
11
|
+
cfn_model.find_security_group_by_group_id(security_group_reference)
|
12
|
+
end
|
13
|
+
load_balancer
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ParserError < RuntimeError
|
2
|
+
attr_accessor :errors
|
3
|
+
|
4
|
+
def initialize(message, validation_errors=nil)
|
5
|
+
super(message)
|
6
|
+
@message = message
|
7
|
+
@errors = validation_errors
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#{@message}#{@errors.nil? ? '' : ':'}#{@errors.to_s}"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Dir["#{__dir__}/*_parser.rb"].each { |model| require "cfn-model/parser/#{File.basename(model, '.rb')}" }
|
2
|
+
|
3
|
+
class ParserRegistry
|
4
|
+
attr_reader :registry
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@registry = {
|
8
|
+
'AWS::EC2::SecurityGroup' => SecurityGroupParser,
|
9
|
+
'AWS::EC2::NetworkInterface' => Ec2NetworkInterfaceParser,
|
10
|
+
'AWS::EC2::Instance' => Ec2InstanceParser,
|
11
|
+
'AWS::ElasticLoadBalancing::LoadBalancer' => LoadBalancerParser,
|
12
|
+
'AWS::ElasticLoadBalancingV2::LoadBalancer' => LoadBalancerV2Parser,
|
13
|
+
'AWS::IAM::Group' => IamGroupParser,
|
14
|
+
'AWS::IAM::User' => IamUserParser,
|
15
|
+
'AWS::IAM::Role' => IamRoleParser,
|
16
|
+
'AWS::IAM::Policy' => WithPolicyDocumentParser,
|
17
|
+
'AWS::IAM::ManagedPolicy' => WithPolicyDocumentParser,
|
18
|
+
'AWS::S3::BucketPolicy' => WithPolicyDocumentParser,
|
19
|
+
'AWS::SNS::TopicPolicy' => WithPolicyDocumentParser,
|
20
|
+
'AWS::SQS::QueuePolicy' => WithPolicyDocumentParser
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.instance
|
25
|
+
if @instance.nil?
|
26
|
+
@instance = ParserRegistry.new
|
27
|
+
end
|
28
|
+
@instance
|
29
|
+
end
|
30
|
+
|
31
|
+
# def add_parser(resource_name, parser)
|
32
|
+
# @registry[resource_name] = parser
|
33
|
+
# end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'cfn-model/model/iam_policy'
|
2
|
+
require 'cfn-model/model/policy_document'
|
3
|
+
|
4
|
+
class PolicyDocumentParser
|
5
|
+
def parse(raw_policy_document)
|
6
|
+
policy_document = PolicyDocument.new
|
7
|
+
|
8
|
+
policy_document.version = raw_policy_document['Version']
|
9
|
+
|
10
|
+
policy_document.statements = streamline_array(raw_policy_document['Statement']) do |statement|
|
11
|
+
parse_statement statement
|
12
|
+
end
|
13
|
+
|
14
|
+
policy_document
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parse_statement(raw_statement)
|
20
|
+
statement = Statement.new
|
21
|
+
statement.effect = raw_statement['Effect']
|
22
|
+
statement.sid = raw_statement['Sid']
|
23
|
+
statement.condition = raw_statement['Condition']
|
24
|
+
statement.actions = streamline_array(raw_statement['Action'])
|
25
|
+
statement.not_actions = streamline_array(raw_statement['NotAction'])
|
26
|
+
statement.resources = streamline_array(raw_statement['Resource'])
|
27
|
+
statement.not_resources = streamline_array(raw_statement['NotResource'])
|
28
|
+
statement.principal = raw_statement['Principal']
|
29
|
+
statement.not_principal = raw_statement['NotPrincipal']
|
30
|
+
statement
|
31
|
+
end
|
32
|
+
|
33
|
+
def streamline_array(one_or_more)
|
34
|
+
return [] if one_or_more.nil?
|
35
|
+
|
36
|
+
if one_or_more.is_a?(String) || one_or_more.is_a?(Hash)
|
37
|
+
[block_given? ? yield(one_or_more) : one_or_more]
|
38
|
+
elsif one_or_more.is_a? Array
|
39
|
+
one_or_more.map { |one| block_given? ? yield(one) : one }
|
40
|
+
else
|
41
|
+
raise "unexpected object in streamline_array: #{one_or_more} #{one_or_more.class}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative 'parser_error'
|
2
|
+
require 'cfn-model/model/security_group_egress'
|
3
|
+
require 'cfn-model/model/security_group_ingress'
|
4
|
+
require 'cfn-model/model/references'
|
5
|
+
|
6
|
+
class SecurityGroupParser
|
7
|
+
|
8
|
+
def parse(cfn_model:, resource:)
|
9
|
+
security_group = resource
|
10
|
+
|
11
|
+
objectify_egress security_group
|
12
|
+
|
13
|
+
objectify_ingress security_group
|
14
|
+
|
15
|
+
wire_ingress_rules_to_security_group(cfn_model: cfn_model, security_group: security_group)
|
16
|
+
wire_egress_rules_to_security_group(cfn_model: cfn_model, security_group: security_group)
|
17
|
+
security_group
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def objectify_ingress(security_group)
|
23
|
+
if security_group.securityGroupIngress.is_a? Hash
|
24
|
+
security_group.securityGroupIngress = [security_group.securityGroupIngress]
|
25
|
+
end
|
26
|
+
|
27
|
+
security_group.ingresses = security_group.securityGroupIngress.map do |ingress|
|
28
|
+
ingress_object = AWS::EC2::SecurityGroupIngress.new
|
29
|
+
ingress.each do |k,v|
|
30
|
+
ingress_object.send("#{initialLower(k)}=", v)
|
31
|
+
end
|
32
|
+
#ingress_object.valid?
|
33
|
+
ingress_object
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def objectify_egress(security_group)
|
38
|
+
if security_group.securityGroupEgress.is_a? Hash
|
39
|
+
security_group.securityGroupEgress = [security_group.securityGroupEgress]
|
40
|
+
end
|
41
|
+
|
42
|
+
security_group.egresses = security_group.securityGroupEgress.map do |egress|
|
43
|
+
egress_object = AWS::EC2::SecurityGroupEgress.new
|
44
|
+
egress.each do |k,v|
|
45
|
+
egress_object.send("#{initialLower(k)}=", v)
|
46
|
+
end
|
47
|
+
#egress_object.valid?
|
48
|
+
egress_object
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialLower(str)
|
53
|
+
str.slice(0).downcase + str[1..(str.length)]
|
54
|
+
end
|
55
|
+
|
56
|
+
def wire_ingress_rules_to_security_group(cfn_model:, security_group:)
|
57
|
+
ingress_rules = cfn_model.resources_by_type 'AWS::EC2::SecurityGroupIngress'
|
58
|
+
ingress_rules.each do |security_group_ingress|
|
59
|
+
group_id = References.resolve_security_group_id(security_group_ingress.groupId)
|
60
|
+
|
61
|
+
# standalone ingress rules are legal - referencing an external security group
|
62
|
+
next if group_id.nil?
|
63
|
+
|
64
|
+
if security_group.logical_resource_id == group_id
|
65
|
+
security_group.ingresses << security_group_ingress
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def wire_egress_rules_to_security_group(cfn_model:, security_group:)
|
71
|
+
egress_rules = cfn_model.resources_by_type 'AWS::EC2::SecurityGroupEgress'
|
72
|
+
egress_rules.each do |security_group_egress|
|
73
|
+
group_id = References.resolve_security_group_id(security_group_egress.groupId)
|
74
|
+
|
75
|
+
# standalone ingress rules are legal - referencing an external security group
|
76
|
+
next if group_id.nil?
|
77
|
+
|
78
|
+
if security_group.logical_resource_id == group_id
|
79
|
+
security_group.egresses << security_group_egress
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'cfn-model/model/iam_policy'
|
2
|
+
require 'cfn-model/model/policy_document'
|
3
|
+
require_relative 'policy_document_parser'
|
4
|
+
|
5
|
+
class WithPolicyDocumentParser
|
6
|
+
def parse(cfn_model:, resource:)
|
7
|
+
resource.policy_document = PolicyDocumentParser.new.parse(resource.policyDocument)
|
8
|
+
resource
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
type: map
|
3
|
+
mapping:
|
4
|
+
Type:
|
5
|
+
type: str
|
6
|
+
required: yes
|
7
|
+
pattern: /AWS::CloudFront::Distribution/
|
8
|
+
Properties:
|
9
|
+
type: map
|
10
|
+
required: yes
|
11
|
+
mapping:
|
12
|
+
DistributionConfig:
|
13
|
+
type: map
|
14
|
+
required: yes
|
15
|
+
mapping:
|
16
|
+
Aliases:
|
17
|
+
type: seq
|
18
|
+
required: no
|
19
|
+
sequence:
|
20
|
+
- type: any
|
21
|
+
CacheBehaviors:
|
22
|
+
type: seq
|
23
|
+
required: no
|
24
|
+
sequence:
|
25
|
+
- type: any
|
26
|
+
DefaultCacheBehavior:
|
27
|
+
type: any
|
28
|
+
required: yes
|
29
|
+
Enabled:
|
30
|
+
type: any
|
31
|
+
required: yes
|
32
|
+
Origins:
|
33
|
+
type: seq
|
34
|
+
required: yes
|
35
|
+
sequence:
|
36
|
+
- type: any
|
37
|
+
=:
|
38
|
+
type: any
|
39
|
+
=:
|
40
|
+
type: any
|
41
|
+
=:
|
42
|
+
type: any
|
@@ -0,0 +1,146 @@
|
|
1
|
+
---
|
2
|
+
type: map
|
3
|
+
mapping:
|
4
|
+
Type:
|
5
|
+
type: str
|
6
|
+
required: yes
|
7
|
+
pattern: /AWS::EC2::Instance/
|
8
|
+
Properties:
|
9
|
+
type: map
|
10
|
+
required: yes
|
11
|
+
mapping:
|
12
|
+
BlockDeviceMappings:
|
13
|
+
type: seq
|
14
|
+
required: no
|
15
|
+
sequence:
|
16
|
+
- type: map
|
17
|
+
mapping:
|
18
|
+
DeviceName:
|
19
|
+
type: any
|
20
|
+
required: yes
|
21
|
+
=:
|
22
|
+
type: any
|
23
|
+
ImageId:
|
24
|
+
type: any
|
25
|
+
required: yes
|
26
|
+
Ipv6Addresses:
|
27
|
+
type: seq
|
28
|
+
required: no
|
29
|
+
sequence:
|
30
|
+
- type: map
|
31
|
+
mapping:
|
32
|
+
Ipv6Address:
|
33
|
+
type: any
|
34
|
+
required: yes
|
35
|
+
=:
|
36
|
+
type: any
|
37
|
+
NetworkInterfaces:
|
38
|
+
type: seq
|
39
|
+
required: no
|
40
|
+
sequence:
|
41
|
+
- type: map
|
42
|
+
mapping:
|
43
|
+
DeviceIndex:
|
44
|
+
type: any
|
45
|
+
required: yes
|
46
|
+
GroupSet:
|
47
|
+
type: seq
|
48
|
+
required: no
|
49
|
+
sequence:
|
50
|
+
- type: any
|
51
|
+
Ipv6Addresses:
|
52
|
+
type: seq
|
53
|
+
required: no
|
54
|
+
sequence:
|
55
|
+
- type: map
|
56
|
+
mapping:
|
57
|
+
Ipv6Address:
|
58
|
+
type: any
|
59
|
+
required: yes
|
60
|
+
=:
|
61
|
+
type: any
|
62
|
+
PrivateIpAddresses:
|
63
|
+
type: seq
|
64
|
+
required: no
|
65
|
+
sequence:
|
66
|
+
- type: map
|
67
|
+
mapping:
|
68
|
+
PrivateIpAddress:
|
69
|
+
type: any
|
70
|
+
required: yes
|
71
|
+
Primary:
|
72
|
+
type: any
|
73
|
+
required: yes
|
74
|
+
=:
|
75
|
+
type: any
|
76
|
+
=:
|
77
|
+
type: any
|
78
|
+
|
79
|
+
# sigh this could be List<AWS::EC2::SecurityGroup::Id> so can't enfore seq
|
80
|
+
SecurityGroupIds:
|
81
|
+
type: any
|
82
|
+
required: no
|
83
|
+
|
84
|
+
# sigh this could be List<AWS::EC2::SecurityGroup::GroupName> so can't enfore seq
|
85
|
+
SecurityGroups:
|
86
|
+
type: any
|
87
|
+
required: no
|
88
|
+
|
89
|
+
SsmAssociations:
|
90
|
+
type: seq
|
91
|
+
required: no
|
92
|
+
sequence:
|
93
|
+
- type: map
|
94
|
+
mapping:
|
95
|
+
AssociationParameters:
|
96
|
+
type: seq
|
97
|
+
required: no
|
98
|
+
sequence:
|
99
|
+
- type: map
|
100
|
+
mapping:
|
101
|
+
Key:
|
102
|
+
type: any
|
103
|
+
required: yes
|
104
|
+
Value:
|
105
|
+
type: seq
|
106
|
+
required: yes
|
107
|
+
sequence:
|
108
|
+
- type: any
|
109
|
+
=:
|
110
|
+
type: any
|
111
|
+
DocumentName:
|
112
|
+
required: yes
|
113
|
+
type: any
|
114
|
+
|
115
|
+
Tags:
|
116
|
+
type: seq
|
117
|
+
required: no
|
118
|
+
sequence:
|
119
|
+
- type: map
|
120
|
+
mapping:
|
121
|
+
Key:
|
122
|
+
type: any
|
123
|
+
required: yes
|
124
|
+
Value:
|
125
|
+
type: any
|
126
|
+
required: yes
|
127
|
+
=:
|
128
|
+
type: any
|
129
|
+
Volumes:
|
130
|
+
type: seq
|
131
|
+
required: no
|
132
|
+
sequence:
|
133
|
+
- type: map
|
134
|
+
mapping:
|
135
|
+
Device:
|
136
|
+
type: any
|
137
|
+
required: yes
|
138
|
+
VolumeId:
|
139
|
+
type: any
|
140
|
+
required: yes
|
141
|
+
=:
|
142
|
+
type: any
|
143
|
+
=:
|
144
|
+
type: any
|
145
|
+
=:
|
146
|
+
type: any
|