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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: df7b00fc32259e430e24108cd53e3f9d6a314415
|
4
|
+
data.tar.gz: fdfe0f37dc53623ffda3fad4cd32b9aaa466b3fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 98060606e4d5a092a4b6619093f770b09b7bdf714a15dd93481f0c3df6b10ba6907afcfe26db0940cdb5a7cf9666b72acf828aa61a40f6e6c1cb6c68286d2f3f
|
7
|
+
data.tar.gz: 4e30e1684419ff1cab3d400dfcf5eb57591c9a6518ae7fea8fd6362788280c5d4bcbca9344eca566f8b4441bed5da4e8433c3ca910cbb652c3cf469eb992bff3
|
data/bin/cfn_parse
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::S3::BucketPolicy < ModelElement
|
4
|
+
# mapped from document
|
5
|
+
attr_accessor :bucket, :policyDocument
|
6
|
+
|
7
|
+
# PolicyDocument - objectified policyDocument
|
8
|
+
attr_accessor :policy_document
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@resource_type = 'AWS::S3::BucketPolicy'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative 'references'
|
2
|
+
|
3
|
+
class CfnModel
|
4
|
+
attr_reader :resources
|
5
|
+
|
6
|
+
##
|
7
|
+
# if you really want it, here it is - the raw Hash from YAML.load. you'll have to mess with structural nits of
|
8
|
+
# CloudFormation and deal with variations between yaml/json refs and all that
|
9
|
+
#
|
10
|
+
attr_accessor :raw_model
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@resources = {}
|
14
|
+
@raw_model = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def security_groups
|
18
|
+
resources_by_type 'AWS::EC2::SecurityGroup'
|
19
|
+
end
|
20
|
+
|
21
|
+
def iam_users
|
22
|
+
resources_by_type 'AWS::IAM::User'
|
23
|
+
end
|
24
|
+
|
25
|
+
def standalone_ingress
|
26
|
+
security_group_ingresses = resources_by_type 'AWS::EC2::SecurityGroupIngress'
|
27
|
+
security_group_ingresses.select do |security_group_ingress|
|
28
|
+
References.is_security_group_id_external(security_group_ingress.groupId)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def standalone_egress
|
33
|
+
security_group_egresses = resources_by_type 'AWS::EC2::SecurityGroupEgress'
|
34
|
+
security_group_egresses.select do |security_group_egress|
|
35
|
+
References.is_security_group_id_external(security_group_egress.groupId)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resources_by_type(resource_type)
|
40
|
+
@resources.values.select { |resource| resource.resource_type == resource_type }
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_security_group_by_group_id(security_group_reference)
|
44
|
+
security_group_id = References.resolve_security_group_id(security_group_reference)
|
45
|
+
if security_group_id.nil?
|
46
|
+
# leave it alone since external ref or something we don't grok
|
47
|
+
security_group_reference
|
48
|
+
else
|
49
|
+
matched_security_group = security_groups.find do |security_group|
|
50
|
+
security_group.logical_resource_id == security_group_id
|
51
|
+
end
|
52
|
+
if matched_security_group.nil?
|
53
|
+
# leave it alone since external ref or something we don't grok
|
54
|
+
security_group_reference
|
55
|
+
else
|
56
|
+
matched_security_group
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
@resources.to_s
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::EC2::Instance < ModelElement
|
4
|
+
attr_accessor :securityGroupIds, :networkInterfaces
|
5
|
+
|
6
|
+
# SecurityGroup objects based upon securityGroupIds
|
7
|
+
attr_accessor :security_groups
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@securityGroupIds = []
|
11
|
+
@networkInterfaces = []
|
12
|
+
@security_groups = []
|
13
|
+
@resource_type = 'AWS::EC2::Instance'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::EC2::NetworkInterface < ModelElement
|
4
|
+
attr_accessor :groupSet, :ipv6Addresses, :privateIpAddresses, :tags
|
5
|
+
attr_accessor :description, :ipv6AddressCount, :privateIpAddress, :secondaryPrivateIpAddressCount, :sourceDestCheck, :subnetId
|
6
|
+
|
7
|
+
# SecurityGroup objects based upon groupSet
|
8
|
+
attr_accessor :security_groups
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@groupSet = []
|
12
|
+
@ipv6Addresses = []
|
13
|
+
@privateIpAddresses = []
|
14
|
+
@tags = []
|
15
|
+
@security_groups = []
|
16
|
+
@resource_type = 'AWS::EC2::NetworkInterface'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::IAM::Group < ModelElement
|
4
|
+
attr_accessor :groupName, :managedPolicyArns, :path, :policies
|
5
|
+
|
6
|
+
# synthesized version of policies
|
7
|
+
attr_accessor :policy_objects
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@managedPolicyArns = []
|
11
|
+
@policies = []
|
12
|
+
@policy_objects = []
|
13
|
+
@resource_type = 'AWS::IAM::Group'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::IAM::ManagedPolicy < ModelElement
|
4
|
+
attr_accessor :description, :managedPolicyName, :policyDocument, :groups, :roles, :users, :path
|
5
|
+
|
6
|
+
attr_accessor :policy_document
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@groups = []
|
10
|
+
@roles = []
|
11
|
+
@users = []
|
12
|
+
@resource_type = 'AWS::IAM::ManagedPolicy'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::IAM::Policy < ModelElement
|
4
|
+
attr_accessor :policyName, :policyDocument, :groups, :roles, :users
|
5
|
+
|
6
|
+
attr_accessor :policy_document
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@groups = []
|
10
|
+
@roles = []
|
11
|
+
@users = []
|
12
|
+
@resource_type = 'AWS::IAM::Policy'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::IAM::Role < ModelElement
|
4
|
+
attr_accessor :roleName, :assumeRolePolicyDocument, :policies, :path, :managedPolicyArns
|
5
|
+
|
6
|
+
attr_accessor :policy_objects, :assume_role_policy_document
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@policies = []
|
10
|
+
@managedPolicyArns = []
|
11
|
+
@policy_objects = []
|
12
|
+
@resource_type = 'AWS::IAM::Role'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::IAM::User < ModelElement
|
4
|
+
attr_accessor :groups, :loginProfile, :path, :policies, :userName
|
5
|
+
|
6
|
+
# synthesized version of policies
|
7
|
+
attr_accessor :policy_objects, :group_names
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@groups = []
|
11
|
+
@policies = []
|
12
|
+
@policy_objects = []
|
13
|
+
@group_names = []
|
14
|
+
@resource_type = 'AWS::IAM::User'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::ElasticLoadBalancing::LoadBalancer < ModelElement
|
4
|
+
attr_accessor :securityGroups, :subnets, :tags, :scheme, :loadBalancerName, :crossZone, :availabilityZones, :connectionDrainingPolicy
|
5
|
+
attr_accessor :connectionSettings, :accessLoggingPolicy, :instances, :appCookieStickinessPolicy, :lBCookieStickinessPolicy, :healthCheck, :policies, :listeners
|
6
|
+
|
7
|
+
attr_accessor :security_groups
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@securityGroups = []
|
11
|
+
@security_groups = []
|
12
|
+
@subnets = []
|
13
|
+
@tags = []
|
14
|
+
@availabilityZones = []
|
15
|
+
@instances = []
|
16
|
+
@appCookieStickinessPolicy = []
|
17
|
+
@lBCookieStickinessPolicy = []
|
18
|
+
@policies = []
|
19
|
+
@listeners = []
|
20
|
+
@resource_type = 'AWS::ElasticLoadBalancing::LoadBalancer'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class AWS::ElasticLoadBalancingV2::LoadBalancer < ModelElement
|
25
|
+
attr_accessor :securityGroups, :loadBalancerAttributes, :subnets, :tags, :scheme, :name, :ipAddressType
|
26
|
+
|
27
|
+
attr_accessor :security_groups
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@securityGroups = []
|
31
|
+
@security_groups = []
|
32
|
+
@loadBalancerAttributes = []
|
33
|
+
@subnets = []
|
34
|
+
@tags = []
|
35
|
+
@resource_type = 'AWS::ElasticLoadBalancingV2::LoadBalancer'
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
module AWS
|
3
|
+
module CloudFormation
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
module EC2
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module ElasticLoadBalancing
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
module ElasticLoadBalancingV2
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
module IAM
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module S3
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
module SNS
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
module SQS
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
module Lambda
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
module CloudFront
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Custom
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
class ModelElement
|
49
|
+
attr_accessor :logical_resource_id, :resource_type
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
<<END
|
53
|
+
{
|
54
|
+
#{emit_instance_vars}
|
55
|
+
}
|
56
|
+
END
|
57
|
+
end
|
58
|
+
|
59
|
+
def ==(another_model_element)
|
60
|
+
found_unequal_instance_var = false
|
61
|
+
instance_variables_without_at_sign.each do |instance_variable|
|
62
|
+
if instance_variable != :logical_resource_id
|
63
|
+
if self.send(instance_variable) != another_model_element.send(instance_variable)
|
64
|
+
found_unequal_instance_var = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
!found_unequal_instance_var
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
##
|
74
|
+
# Treat any missing method as an instance variable get/set
|
75
|
+
#
|
76
|
+
# This will allow arbitrary elements in Resource/Properties definitions
|
77
|
+
# to map to instance variables without having to anticipate them in a schema
|
78
|
+
def method_missing(method_name, *args)
|
79
|
+
if method_name =~ /^(\w+)=$/
|
80
|
+
instance_variable_set "@#{$1}", args[0]
|
81
|
+
else
|
82
|
+
instance_variable_get "@#{method_name}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def instance_variables_without_at_sign
|
87
|
+
self.instance_variables.map { |instance_variable| strip(instance_variable) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def strip(sym)
|
91
|
+
sym.to_s.gsub(/@/, '').to_sym
|
92
|
+
end
|
93
|
+
|
94
|
+
def emit_instance_vars
|
95
|
+
instance_vars_str = ''
|
96
|
+
self.instance_variables.each do |instance_variable|
|
97
|
+
instance_vars_str += " #{instance_variable}=#{instance_variable_get(instance_variable)}\n"
|
98
|
+
end
|
99
|
+
instance_vars_str
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'statement'
|
2
|
+
|
3
|
+
class PolicyDocument
|
4
|
+
attr_accessor :version, :statements
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@statements = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def wildcard_allowed_resources
|
11
|
+
@statements.select { |statement| !statement.wildcard_resources.empty? && statement.effect == 'Allow' }
|
12
|
+
end
|
13
|
+
|
14
|
+
def wildcard_allowed_actions
|
15
|
+
@statements.select { |statement| !statement.wildcard_actions.empty? && statement.effect == 'Allow' }
|
16
|
+
end
|
17
|
+
|
18
|
+
def wildcard_allowed_principals
|
19
|
+
@statements.select { |statement| statement.wildcard_principal? && statement.effect == 'Allow' }
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Select any Statement objects that Allow in conjunction with a NotAction
|
24
|
+
#
|
25
|
+
def allows_not_action
|
26
|
+
@statements.select { |statement| !statement.not_actions.empty? && statement.effect == 'Allow' }
|
27
|
+
end
|
28
|
+
|
29
|
+
def allows_not_resource
|
30
|
+
@statements.select { |statement| !statement.not_resources.empty? && statement.effect == 'Allow' }
|
31
|
+
end
|
32
|
+
|
33
|
+
def allows_not_principal
|
34
|
+
@statements.select { |statement| !statement.not_principal.nil? && statement.effect == 'Allow' }
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(another_doc)
|
38
|
+
@version == another_doc.version && @statements == another_doc.statements
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
<<END
|
43
|
+
{
|
44
|
+
version=#{@version}
|
45
|
+
statements=#{@statements}
|
46
|
+
}
|
47
|
+
END
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Principal
|
2
|
+
def self.wildcard?(principal)
|
3
|
+
if principal.is_a? String
|
4
|
+
return has_asterisk principal
|
5
|
+
elsif principal.is_a? Hash
|
6
|
+
# if new principal types arrive, let's not tie ourselves down - the * is still likely the thing to look for
|
7
|
+
# unless %w(AWS FederatedUser CanonicalUser Service).include?(principal.keys.first)
|
8
|
+
# raise "whacky principal key: #{principal}"
|
9
|
+
# end
|
10
|
+
|
11
|
+
has_wildcard = false
|
12
|
+
principal.values.each do |principal_value|
|
13
|
+
if principal_value.is_a? String
|
14
|
+
has_wildcard ||= has_asterisk principal_value
|
15
|
+
elsif principal_value.is_a? Array
|
16
|
+
wildcard_principal = principal_value.find { |principal_iter| principal_iter =~ /\*/ }
|
17
|
+
has_wildcard ||= !wildcard_principal.nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
has_wildcard
|
21
|
+
elsif principal.nil?
|
22
|
+
false
|
23
|
+
else
|
24
|
+
# array? not legal?
|
25
|
+
raise "whacky principal not string or hash: #{principal}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.has_asterisk(string)
|
32
|
+
!(string =~ /\*/).nil?
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::SQS::QueuePolicy < ModelElement
|
4
|
+
attr_accessor :queues, :policyDocument
|
5
|
+
|
6
|
+
# PolicyDocument - objectified policyDocument
|
7
|
+
attr_accessor :policy_document
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@queues = []
|
11
|
+
@resource_type = 'AWS::SQS::QueuePolicy'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
##
|
3
|
+
# this is a placeholder for anything related to resolving references
|
4
|
+
#
|
5
|
+
# not sure if we are going to be able to have a useful generic set of code for
|
6
|
+
# references yet... in the meantime pile things up here and hope a pattern becomes
|
7
|
+
# clear
|
8
|
+
module References
|
9
|
+
def self.is_security_group_id_external(group_id)
|
10
|
+
resolve_security_group_id(group_id).nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Return nil if
|
15
|
+
def self.resolve_security_group_id(group_id)
|
16
|
+
return nil if group_id.is_a? String
|
17
|
+
|
18
|
+
# an imported value can only yield a literal to an external sg vs. referencing something local
|
19
|
+
if !group_id['Ref'].nil?
|
20
|
+
group_id['Ref']
|
21
|
+
elsif !group_id['Fn::GetAtt'].nil?
|
22
|
+
logical_resource_id_from_get_att group_id['Fn::GetAtt']
|
23
|
+
else # !group_id['Fn::ImportValue'].nil?
|
24
|
+
# anything else will be string manipulation functions
|
25
|
+
# which again leads us back to a string which must be an external security group known out of band
|
26
|
+
# so don't/can't link it up to a security group
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.logical_resource_id_from_get_att(attribute_spec)
|
34
|
+
if attribute_spec.is_a? Array
|
35
|
+
if attribute_spec[1] == 'GroupId'
|
36
|
+
return attribute_spec.first
|
37
|
+
else
|
38
|
+
# this could be a reference to a nested stack output so treat it as external
|
39
|
+
# and presume the ingress is freestanding.
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
elsif attribute_spec.is_a? String
|
43
|
+
if attribute_spec.split('.')[1] == 'GroupId'
|
44
|
+
return attribute_spec.split('.').first
|
45
|
+
else
|
46
|
+
# this could be a reference to a nested stack output so treat it as external
|
47
|
+
# and presume the ingress is freestanding.
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::EC2::SecurityGroup < ModelElement
|
4
|
+
attr_accessor :groupDescription, :vpcId
|
5
|
+
attr_accessor :tags
|
6
|
+
attr_accessor :securityGroupIngress, :securityGroupEgress
|
7
|
+
|
8
|
+
attr_accessor :ingresses, :egresses
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@securityGroupIngress = []
|
12
|
+
@securityGroupEgress = []
|
13
|
+
@ingresses = []
|
14
|
+
@egresses = []
|
15
|
+
@tags = []
|
16
|
+
@resource_type = 'AWS::EC2::SecurityGroup'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
# this could have been inline or freestanding
|
4
|
+
# in latter case there would be a logical resource id
|
5
|
+
# but i think we don't ever care?
|
6
|
+
class AWS::EC2::SecurityGroupEgress < ModelElement
|
7
|
+
# You must specify a destination security group (destinationPrefixListId or destinationSecurityGroupId) or a CIDR range (CidrIp or CidrIpv6).
|
8
|
+
attr_accessor :cidrIp,
|
9
|
+
:cidrIpv6,
|
10
|
+
:destinationPrefixListId,
|
11
|
+
:destinationSecurityGroupId
|
12
|
+
|
13
|
+
# required
|
14
|
+
attr_accessor :groupId,
|
15
|
+
:fromPort,
|
16
|
+
:toPort,
|
17
|
+
:ipProtocol
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@resource_type = 'AWS::EC2::SecurityGroupEgress'
|
21
|
+
end
|
22
|
+
|
23
|
+
# def valid?
|
24
|
+
# has_no_destination = @cidrIp.nil? && @cidrIpv6.nil? && @destinationPrefixListId.nil? && @destinationSecurityGroupId.nil?
|
25
|
+
# if has_no_destination
|
26
|
+
# raise "SG egress #{@logical_resource_id} has no destination specified"
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
# this could have been inline or freestanding
|
4
|
+
# in latter case there would be a logical resource id
|
5
|
+
# but i think we don't ever care?
|
6
|
+
class AWS::EC2::SecurityGroupIngress < ModelElement
|
7
|
+
# You must specify a source security group (SourceSecurityGroupName or SourceSecurityGroupId) or a CIDR range (CidrIp or CidrIpv6).
|
8
|
+
attr_accessor :cidrIp,
|
9
|
+
:cidrIpv6,
|
10
|
+
:sourceSecurityGroupName,
|
11
|
+
:sourceSecurityGroupId
|
12
|
+
|
13
|
+
# Required: Conditional. You must specify the GroupName property or the GroupId property.
|
14
|
+
# For security groups that are in a VPC, you must use the GroupId property. For example, EC2-VPC accounts must use the GroupId property.
|
15
|
+
# this will be nil for inline ingress rules
|
16
|
+
attr_accessor :groupId,
|
17
|
+
:groupName
|
18
|
+
|
19
|
+
# required
|
20
|
+
attr_accessor :fromPort,
|
21
|
+
:toPort,
|
22
|
+
:ipProtocol
|
23
|
+
|
24
|
+
# Required: Conditional. If you specify SourceSecurityGroupName and that security group is owned by a different
|
25
|
+
# account than the account creating the stack, you must specify the SourceSecurityGroupOwnerId; otherwise, this property is optional.
|
26
|
+
attr_accessor :sourceSecurityGroupOwnerId
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@resource_type = 'AWS::EC2::SecurityGroupIngress'
|
30
|
+
end
|
31
|
+
|
32
|
+
# def valid?
|
33
|
+
# has_no_source = @cidrIp.nil? && @cidrIpv6.nil? && @sourceSecurityGroupName.nil? && @sourceSecurityGroupId.nil?
|
34
|
+
# if has_no_source
|
35
|
+
# raise "SG ingress #{@logical_resource_id} has no source specified"
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'principal'
|
2
|
+
|
3
|
+
class Statement
|
4
|
+
attr_accessor :sid, :effect, :condition
|
5
|
+
attr_accessor :actions, :not_actions
|
6
|
+
attr_accessor :resources, :not_resources
|
7
|
+
attr_accessor :principal, :not_principal
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@actions = []
|
11
|
+
@not_actions = []
|
12
|
+
@resources = []
|
13
|
+
@not_resources = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def wildcard_actions
|
17
|
+
@actions.select { |action| action.to_s =~ /\*/ }
|
18
|
+
end
|
19
|
+
|
20
|
+
def wildcard_principal?
|
21
|
+
Principal.wildcard? @principal
|
22
|
+
end
|
23
|
+
|
24
|
+
def wildcard_resources
|
25
|
+
@resources.select { |action| action.to_s =~ /\*/ }
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(another_statement)
|
29
|
+
@effect == another_statement.effect &&
|
30
|
+
@actions == another_statement.actions &&
|
31
|
+
@not_actions == another_statement.not_actions &&
|
32
|
+
@resources == another_statement.resources &&
|
33
|
+
@not_resources == another_statement.not_resources &&
|
34
|
+
@principal == another_statement.principal &&
|
35
|
+
@not_principal == another_statement.not_principal &&
|
36
|
+
@condition == another_statement.condition
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'model_element'
|
2
|
+
|
3
|
+
class AWS::SNS::TopicPolicy < ModelElement
|
4
|
+
attr_accessor :topics, :policyDocument
|
5
|
+
|
6
|
+
# PolicyDocument - objectified policyDocument
|
7
|
+
attr_accessor :policy_document
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@topics = []
|
11
|
+
@resource_type = 'AWS::SNS::TopicPolicy'
|
12
|
+
end
|
13
|
+
end
|