cfhighlander 0.2.0.alpha.10

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.
@@ -0,0 +1,172 @@
1
+ ec2-describe:
2
+ action:
3
+ - ec2:Describe*
4
+ - autoscaling:Describe*
5
+ - elasticloadbalancing:Describe*
6
+
7
+ ec2-cleanup-eni:
8
+ action:
9
+ - ec2:DeleteNetworkInterface
10
+ - ec2:DetachNetworkInterface
11
+
12
+ ec2-create-tag:
13
+ action:
14
+ - ec2:CreateTags
15
+
16
+ cloudwatch-logs:
17
+ action:
18
+ - logs:CreateLogGroup
19
+ - logs:CreateLogStream
20
+ - logs:PutLogEvents
21
+ - logs:DescribeLogStreams
22
+ - logs:DescribeLogGroups
23
+ resource:
24
+ - arn:aws:logs:*:*:*
25
+
26
+ cloudwatch-monitoring-writer:
27
+ action:
28
+ - cloudwatch:PutMetricData
29
+
30
+ cloudwatch-monitoring:
31
+ action:
32
+ - cloudwatch:PutMetricData
33
+ - cloudwatch:GetMetricStatistics
34
+ - cloudwatch:ListMetrics
35
+
36
+ s3-list-buckets:
37
+ action:
38
+ - s3:ListAllMyBuckets
39
+ - s3:ListBucket
40
+
41
+ s3-chef-ro:
42
+ action:
43
+ - s3:Get*
44
+ - s3:List*
45
+ resource:
46
+ - arn:aws:s3:::%{source_bucket}/chef
47
+ - arn:aws:s3:::%{source_bucket}/chef/*
48
+
49
+ s3-codedeploy-ro:
50
+ action:
51
+ - s3:Get*
52
+ - s3:List*
53
+ resource:
54
+ - arn:aws:s3:::%{source_bucket}/codedeploy
55
+ - arn:aws:s3:::%{source_bucket}/codedeploy/*
56
+
57
+ ecs-container-instance:
58
+ action:
59
+ - ecs:CreateCluster
60
+ - ecs:DeregisterContainerInstance
61
+ - ecs:DiscoverPollEndpoint
62
+ - ecs:Poll
63
+ - ecs:RegisterContainerInstance
64
+ - ecs:StartTelemetrySession
65
+ - ecs:Submit*
66
+ - ecr:GetAuthorizationToken
67
+ - ecr:BatchCheckLayerAvailability
68
+ - ecr:GetDownloadUrlForLayer
69
+ - ecr:BatchGetImage
70
+ - logs:CreateLogStream
71
+ - logs:PutLogEvents
72
+
73
+ ecs-service-role:
74
+ action:
75
+ - ecs:CreateCluster
76
+ - ecs:DeregisterContainerInstance
77
+ - ecs:DiscoverPollEndpoint
78
+ - ecs:Poll
79
+ - ecs:RegisterContainerInstance
80
+ - ecs:StartTelemetrySession
81
+ - ecs:Submit*
82
+ - ec2:AuthorizeSecurityGroupIngress
83
+ - ec2:Describe*
84
+ - elasticloadbalancing:DeregisterInstancesFromLoadBalancer
85
+ - elasticloadbalancing:Describe*
86
+ - elasticloadbalancing:RegisterInstancesWithLoadBalancer
87
+ - elasticloadbalancing:RegisterTargets
88
+ - elasticloadbalancing:DeregisterTargets
89
+ - autoscaling:Describe*
90
+
91
+ ecr-pull-images:
92
+ action:
93
+ - ecr:BatchCheckLayerAvailability
94
+ - ecr:BatchGetImage
95
+ - ecr:Get*
96
+ - ecr:List*
97
+
98
+ attach-ebs-volume:
99
+ action:
100
+ - ec2:DescribeVolumes
101
+ - ec2:AttachVolume
102
+ - ec2:DetachVolume
103
+
104
+ attach-network-interface:
105
+ action:
106
+ - ec2:DescribeNetworkInterfaces
107
+ - ec2:AttachNetworkInterface
108
+ - ec2:DetachNetworkInterface
109
+
110
+ associate-address:
111
+ action:
112
+ - ec2:AssociateAddress
113
+
114
+ ssm:
115
+ action:
116
+ - ssm:DescribeAssociation
117
+ - ssm:GetDeployablePatchSnapshotForInstance
118
+ - ssm:GetDocument
119
+ - ssm:GetParameters
120
+ - ssm:DescribeParameters
121
+ - ssm:ListAssociations
122
+ - ssm:ListInstanceAssociations
123
+ - ssm:PutInventory
124
+ - ssm:UpdateAssociationStatus
125
+ - ssm:UpdateInstanceAssociationStatus
126
+ - ssm:UpdateInstanceInformation
127
+
128
+ ec2messages:
129
+ action:
130
+ - ec2messages:AcknowledgeMessage
131
+ - ec2messages:DeleteMessage
132
+ - ec2messages:FailMessage
133
+ - ec2messages:GetEndpoint
134
+ - ec2messages:GetMessages
135
+ - ec2messages:SendReply
136
+
137
+ rds-backup-restore:
138
+ action:
139
+ - s3:ListBucket
140
+ - s3:GetBucketLocation
141
+ - s3:GetObjectMetaData
142
+ - s3:GetObject
143
+ - s3:PutObject
144
+ - s3:ListMultipartUploadParts
145
+ - s3:AbortMultipartUpload
146
+ resource:
147
+ - Fn::Join:
148
+ - ""
149
+ -
150
+ - 'arn:aws:s3:::'
151
+ - Fn::FindInMap:
152
+ - 'AccountId'
153
+ - Ref: 'AWS::AccountId'
154
+ - 'DatabaseBucket'
155
+ - Fn::Join:
156
+ - ""
157
+ -
158
+ - 'arn:aws:s3:::'
159
+ - Fn::FindInMap:
160
+ - 'AccountId'
161
+ - Ref: 'AWS::AccountId'
162
+ - 'DatabaseBucket'
163
+ - '/*'
164
+
165
+ spot-role:
166
+ action:
167
+ - ec2:DescribeImages
168
+ - ec2:DescribeSubnets
169
+ - ec2:RequestSpotInstances
170
+ - ec2:TerminateInstances
171
+ - ec2:DescribeInstanceStatus
172
+ - iam:PassRole
@@ -0,0 +1,55 @@
1
+ def service_role_assume_policy(service)
2
+ unless service.end_with? '.amazonaws.com'
3
+ service = "#{service}.amazonaws.com"
4
+ end
5
+ return {
6
+ Version: '2012-10-17',
7
+ Statement: [{ Effect: 'Allow', Principal: { Service: "#{service}" }, Action: 'sts:AssumeRole' }]
8
+ }
9
+ end
10
+
11
+
12
+ def iam_policy_allow(name, actions, resource='*')
13
+
14
+ return {
15
+ PolicyName: name,
16
+ PolicyDocument: {
17
+ Statement: [{
18
+ Sid: name.gsub('_', '').gsub('-', '').downcase,
19
+ Action: actions,
20
+ Resource: resource,
21
+ Effect: 'Allow'
22
+ }]
23
+ }
24
+ }
25
+ end
26
+
27
+ class IAMPolicies
28
+
29
+ def initialize(custom_policies = nil)
30
+ @managed_policies = YAML.load(File.read("#{File.dirname(__FILE__)}/config/managed_policies.yaml"))
31
+ @policy_array = Array.new
32
+ @policies = (not custom_policies.nil?) ? @managed_policies.merge(custom_policies) : @managed_policies
33
+ end
34
+
35
+ def get_policies(group = nil)
36
+ if group.kind_of?(Array)
37
+ puts group
38
+ create_policies(group)
39
+ else
40
+ create_policies(@config['default_policies']) if @config.key?('default_policies')
41
+ create_policies(@config['group_policies'][group]) unless group.nil?
42
+ end
43
+ return @policy_array
44
+ end
45
+
46
+ def create_policies(policies)
47
+ policies.each do |policy|
48
+ raise "ERROR: #{policy} policy doesn't exist in the managed policies or as a custom policy" if !@policies.key?(policy)
49
+ resource = (@policies[policy].key?('resource') ? (@policies[policy]['resource']) : ["*"])
50
+ @policy_array << { PolicyName: policy, PolicyDocument: { Statement: [{ Effect: 'Allow', Action: @policies[policy]['action'], Resource: resource }] } }
51
+ end
52
+ return @policy_array
53
+ end
54
+
55
+ end
@@ -0,0 +1,86 @@
1
+ require_relative './iam_helper'
2
+
3
+ def render_lambda_functions(cfndsl, lambdas, lambda_metadata, distribution)
4
+
5
+ custom_policies = (lambdas.key? 'custom_policies') ? lambdas['custom_policies'] : {}
6
+ lambdas['roles'].each do |lambda_role, role_config|
7
+ cfndsl.IAM_Role("LambdaRole#{lambda_role}") do
8
+ AssumeRolePolicyDocument service_role_assume_policy('lambda')
9
+ Path '/'
10
+ unless role_config['policies_inline'].nil?
11
+ Policies(
12
+ IAMPolicies.new(custom_policies).create_policies(role_config['policies_inline'])
13
+ )
14
+ end
15
+
16
+ unless role_config['policies_managed'].nil?
17
+ ManagedPolicyArns(role_config['policies_managed'])
18
+ end
19
+ end
20
+ end
21
+
22
+ lambdas['functions'].each do |key, lambda_config|
23
+ name = key
24
+ environment = lambda_config['environment'] || {}
25
+
26
+ # Create Lambda function
27
+ function_name = name
28
+ Lambda_Function(function_name) do
29
+ Code({
30
+ S3Bucket: distribution['bucket'],
31
+ S3Key: "#{distribution['prefix']}/#{distribution['version']}/#{lambda_metadata['path'][key]}"
32
+ })
33
+
34
+ Environment(Variables: Hash[environment.collect { |k, v| [k, v] }])
35
+
36
+ Handler(lambda_config['handler'] || 'index.handler')
37
+ MemorySize(lambda_config['memory'] || 128)
38
+ Role(FnGetAtt("LambdaRole#{lambda_config['role']}", 'Arn'))
39
+ Runtime(lambda_config['runtime'])
40
+ Timeout(lambda_config['timeout'] || 10)
41
+ if !lambda_config['vpc'].nil? && lambda_config['vpc']
42
+ # TODO implement VPC config
43
+ end
44
+
45
+ if !lambda_config['named'].nil? && lambda_config['named']
46
+ FunctionName(name)
47
+ end
48
+ end
49
+
50
+ Lambda_Version("#{name}Version#{lambda_metadata['version'][key]}") do
51
+ DeletionPolicy('Retain')
52
+ FunctionName(Ref(name))
53
+ CodeSha256(lambda_metadata['sha256'][key])
54
+ end
55
+
56
+ # Generate lambda function Policy
57
+ unless lambda_config['allowed_sources'].nil?
58
+ i = 1
59
+ lambda_config['allowed_sources'].each do |source|
60
+ Lambda_Permission("#{name}Permissions#{i}") do
61
+ FunctionName(Ref(name))
62
+ Action('lambda:InvokeFunction')
63
+ Principal(source['principal'])
64
+ end
65
+ i += 1
66
+ end
67
+ end
68
+
69
+ # Scheduled triggering of lambda function
70
+ if lambda_config.key?('schedules')
71
+ lambda_config['schedules'].each_with_index do |schedule, index|
72
+ Events_Rule("Lambda#{name}Schedule#{index}") do
73
+ ScheduleExpression("cron(#{schedule['cronExpression']})")
74
+ State('ENABLED')
75
+ target = {
76
+ 'Arn' => FnGetAtt(name, 'Arn'), 'Id' => "lambda#{name}",
77
+ }
78
+ target['Input'] = schedule['payload'] if schedule.key?('payload')
79
+ Targets([target])
80
+ end
81
+ end
82
+ end
83
+
84
+
85
+ end
86
+ end
data/cfndsl_ext/sg.rb ADDED
@@ -0,0 +1,26 @@
1
+
2
+ def sg_create_rules (x, ip_blocks={})
3
+ rules = []
4
+ x.each do | group |
5
+ group['ips'].each do |ip|
6
+ group['rules'].each do |rule|
7
+ lookup_ips_for_sg(ip_blocks, ip).each do |cidr|
8
+ rules << { IpProtocol: "#{rule['IpProtocol']}", FromPort: "#{rule['FromPort']}", ToPort: "#{rule['ToPort']}", CidrIp: cidr }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ return rules
14
+ end
15
+
16
+
17
+ def lookup_ips_for_sg (ips, ip_block_name={})
18
+ if ip_block_name == 'stack'
19
+ cidr = [FnJoin( "", [ "10.", Ref('StackOctet'), ".", "0.0/16" ] )]
20
+ elsif ips.has_key? ip_block_name
21
+ cidr = ips[ip_block_name]
22
+ else
23
+ cidr = [ip_block_name]
24
+ end
25
+ cidr
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'aws-sdk-s3'
2
+
3
+ def aws_credentials
4
+ # TODO implement credentials e.g. for environment create/update/delete
5
+ end
6
+
7
+ def s3_bucket_region(bucket)
8
+ s3 = Aws::S3::Client.new
9
+ location = s3.get_bucket_location({ bucket: bucket }).location_constraint
10
+ location = 'us-east-1' if location == ''
11
+ location = 'eu-west-1' if location == 'EU'
12
+ location
13
+ end
@@ -0,0 +1,21 @@
1
+ class ::Hash
2
+ def deep_merge(second)
3
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
4
+ self.merge(second.to_h, &merger)
5
+ end
6
+
7
+
8
+ def extend(second)
9
+ second.each { |k, v|
10
+
11
+ if ((self.key? k) and (v.is_a? Hash and self[k].is_a? Hash))
12
+ self[k].extend(v)
13
+ else
14
+ self[k] = v
15
+ end
16
+
17
+ } if second.is_a? Hash
18
+
19
+ self
20
+ end
21
+ end
@@ -0,0 +1,99 @@
1
+ require_relative '../lib/highlander.mapproviders'
2
+
3
+ # Return mapping provider as class
4
+ def mappings_provider(provider_name)
5
+ return nil if provider_name.nil?
6
+ provider = nil
7
+ providers = Object.const_get('Highlander').const_get('MapProviders')
8
+ begin
9
+ providers.const_get(provider_name)
10
+ rescue NameError => e
11
+ if e.to_s.include? 'uninitialized constant Highlander::MapProviders::'
12
+ return nil
13
+ end
14
+ STDERR.puts(e.to_s)
15
+ raise e
16
+ end
17
+ end
18
+
19
+ # Return all of the maps from mapping provider
20
+ def mappings_provider_maps(provider_name, config)
21
+ provider = mappings_provider(provider_name)
22
+
23
+ if provider.nil?
24
+ STDERR.puts("Can't find mapping provider #{provider_name} and it's maps")
25
+ return nil
26
+ else
27
+ return provider.getMaps(config)
28
+ end
29
+ end
30
+
31
+ # Renders CloudFormation function for retrieving Mapping value. If key name and map name are not given,
32
+ # extraction from mapping provider will be tried
33
+ def mapping_value(component:, provider_name:, value_name:, key_name: nil)
34
+
35
+ provider = nil
36
+
37
+ # if key name is nil, provider must provide key
38
+ if key_name.nil?
39
+ provider = mappings_provider(provider_name)
40
+ if provider.nil?
41
+ STDERR.puts("Error: mapping provider #{provider_name} not found, can't render value of #{value_name} attribute")
42
+ return nil
43
+ end
44
+ unless provider.respond_to? 'getDefaultKey'
45
+ STDERR.puts("Error: #{provider} does not implement getDefaultKey. Can't render value of #{value_name} attribtue")
46
+ return nil
47
+ end
48
+
49
+ key_name = provider.getDefaultKey
50
+ end
51
+
52
+ # Map name defaults to provider name. If provider exists and implements getMapName
53
+ # map name will be dynamically resolved via this method
54
+ map_name = provider_name
55
+
56
+ provider = mappings_provider(provider_name) if provider.nil?
57
+ unless provider.nil?
58
+ if provider.respond_to? 'getMapName'
59
+ map_name = provider.getMapName
60
+ end
61
+ end
62
+
63
+ # there is no provider
64
+ # and map name is not a reference
65
+ if((provider.nil?) and (not map_name.start_with? 'Ref('))
66
+ # check if mapping exists on component
67
+ unless ((component.config['mappings'].key? map_name))
68
+ STDERR.puts("Could not resolve mapping value: MapName=#{map_name},Key=#{key_name},Attribute=#{value_name}")
69
+ return nil
70
+ end
71
+ end
72
+
73
+ # both map name and key name could be predefined via intrinsic functions
74
+ if map_name.class == Hash
75
+ map_name = map_name.to_s
76
+ elsif( not map_name.include? 'Ref(')
77
+ map_name = "'#{map_name}'"
78
+ end
79
+
80
+ if key_name.class == Hash
81
+ key_name = key_name.to_s
82
+ elsif( not key_name.include? 'Ref(')
83
+ key_name = "'#{key_name}'"
84
+ end
85
+
86
+ if value_name.nil?
87
+ STDERR.puts("No value defined for mapping parameter. MapName=#{map_name},Key=#{key_name},Attribute=#{value_name}")
88
+ return nil
89
+ end
90
+ if value_name.class == Hash
91
+ value_name = value_name.to_s
92
+ elsif( not value_name.include? 'Ref(')
93
+ value_name = "'#{value_name}'"
94
+ end
95
+
96
+
97
+ return "FnFindInMap(#{map_name},#{key_name},#{value_name})"
98
+
99
+ end
data/hl_ext/vpc.rb ADDED
@@ -0,0 +1,12 @@
1
+ def subnet_parameters(subnets, maximum_availability_zones)
2
+ subnets.each { |subnet_name, subnet_config|
3
+ # Account mappings for AZs
4
+ maximum_availability_zones.times do |x|
5
+
6
+ # Request output from other component as input
7
+ # to this component
8
+ OutputParam component: 'vpc', name: "Subnet#{subnet_config['name']}#{x}"
9
+
10
+ end
11
+ }
12
+ end