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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/bin/cfn_parse +8 -0
  3. data/lib/cfn-model/model/bucket_policy.rb +13 -0
  4. data/lib/cfn-model/model/cfn_model.rb +64 -0
  5. data/lib/cfn-model/model/ec2_instance.rb +15 -0
  6. data/lib/cfn-model/model/ec2_network_interface.rb +18 -0
  7. data/lib/cfn-model/model/iam_group.rb +15 -0
  8. data/lib/cfn-model/model/iam_managed_policy.rb +14 -0
  9. data/lib/cfn-model/model/iam_policy.rb +14 -0
  10. data/lib/cfn-model/model/iam_role.rb +14 -0
  11. data/lib/cfn-model/model/iam_user.rb +16 -0
  12. data/lib/cfn-model/model/iam_user_to_group_addition.rb +10 -0
  13. data/lib/cfn-model/model/load_balancer.rb +37 -0
  14. data/lib/cfn-model/model/model_element.rb +101 -0
  15. data/lib/cfn-model/model/policy.rb +10 -0
  16. data/lib/cfn-model/model/policy_document.rb +52 -0
  17. data/lib/cfn-model/model/principal.rb +34 -0
  18. data/lib/cfn-model/model/queue_policy.rb +13 -0
  19. data/lib/cfn-model/model/references.rb +52 -0
  20. data/lib/cfn-model/model/security_group.rb +18 -0
  21. data/lib/cfn-model/model/security_group_egress.rb +29 -0
  22. data/lib/cfn-model/model/security_group_ingress.rb +38 -0
  23. data/lib/cfn-model/model/statement.rb +38 -0
  24. data/lib/cfn-model/model/topic_policy.rb +13 -0
  25. data/lib/cfn-model/parser/cfn_parser.rb +126 -0
  26. data/lib/cfn-model/parser/ec2_instance_parser.rb +10 -0
  27. data/lib/cfn-model/parser/ec2_network_interface_parser.rb +10 -0
  28. data/lib/cfn-model/parser/iam_group_parser.rb +17 -0
  29. data/lib/cfn-model/parser/iam_role_parser.rb +20 -0
  30. data/lib/cfn-model/parser/iam_user_parser.rb +58 -0
  31. data/lib/cfn-model/parser/load_balancer_parser.rb +10 -0
  32. data/lib/cfn-model/parser/load_balancer_v2_parser.rb +15 -0
  33. data/lib/cfn-model/parser/parser_error.rb +13 -0
  34. data/lib/cfn-model/parser/parser_registry.rb +34 -0
  35. data/lib/cfn-model/parser/policy_document_parser.rb +44 -0
  36. data/lib/cfn-model/parser/security_group_parser.rb +83 -0
  37. data/lib/cfn-model/parser/with_policy_document_parser.rb +10 -0
  38. data/lib/cfn-model/schema/AWS_CloudFront_Distribution.yml +42 -0
  39. data/lib/cfn-model/schema/AWS_EC2_Instance.yml +146 -0
  40. data/lib/cfn-model/schema/AWS_EC2_NetworkInterface.yml +62 -0
  41. data/lib/cfn-model/schema/AWS_EC2_NetworkInterfaceAttachment.yml +24 -0
  42. data/lib/cfn-model/schema/AWS_EC2_SecurityGroup.yml +71 -0
  43. data/lib/cfn-model/schema/AWS_EC2_SecurityGroupEgress.yml +27 -0
  44. data/lib/cfn-model/schema/AWS_EC2_SecurityGroupIngress.yml +27 -0
  45. data/lib/cfn-model/schema/AWS_ElasticLoadBalancingV2_LoadBalancer.yml +56 -0
  46. data/lib/cfn-model/schema/AWS_ElasticLoadBalancing_LoadBalancer.yml +188 -0
  47. data/lib/cfn-model/schema/AWS_IAM_Group.yml +23 -0
  48. data/lib/cfn-model/schema/AWS_IAM_ManagedPolicy.yml +34 -0
  49. data/lib/cfn-model/schema/AWS_IAM_Policy.yml +36 -0
  50. data/lib/cfn-model/schema/AWS_IAM_Role.yml +28 -0
  51. data/lib/cfn-model/schema/AWS_IAM_User.yml +38 -0
  52. data/lib/cfn-model/schema/AWS_IAM_UserToGroupAddition.yml +23 -0
  53. data/lib/cfn-model/schema/AWS_Lambda_Permission.yml +24 -0
  54. data/lib/cfn-model/schema/AWS_S3_BucketPolicy.yml +21 -0
  55. data/lib/cfn-model/schema/AWS_SNS_TopicPolicy.yml +23 -0
  56. data/lib/cfn-model/schema/AWS_SQS_QueuePolicy.yml +23 -0
  57. data/lib/cfn-model/schema/schema.yml.erb +17 -0
  58. data/lib/cfn-model/validator/cloudformation_validator.rb +12 -0
  59. data/lib/cfn-model/validator/reference_validator.rb +83 -0
  60. data/lib/cfn-model/validator/resource_type_validator.rb +34 -0
  61. data/lib/cfn-model/validator/schema_generator.rb +86 -0
  62. data/lib/cfn-model.rb +2 -0
  63. 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,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'cfn-model'
3
+
4
+ puts '======'
5
+ puts ARGV[0]
6
+ puts '======'
7
+ cfn_model = CfnParser.new.parse IO.read(ARGV[0])
8
+ puts cfn_model
@@ -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,10 @@
1
+ require_relative 'model_element'
2
+
3
+ class AWS::IAM::UserToGroupAddition < ModelElement
4
+ attr_accessor :groupName, :users
5
+
6
+ def initialize
7
+ @users = []
8
+ @resource_type = 'AWS::IAM::UserToGroupAddition'
9
+ end
10
+ 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,10 @@
1
+ require_relative 'model_element'
2
+
3
+ class Policy
4
+ attr_accessor :policy_name, :policy_document
5
+
6
+ def ==(another_policy)
7
+ policy_name == another_policy.policy_name &&
8
+ policy_document == another_policy.policy_document
9
+ end
10
+ 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