cfn-model 0.0.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.
- 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
|