ciinabox-ecs 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +458 -0
- data/Rakefile +649 -0
- data/bin/Rakefile +1 -0
- data/bin/ciinabox-ecs +2 -0
- data/bin/ciinabox-ecs.rb +60 -0
- data/config/ciinabox_params.yml.erb +71 -0
- data/config/default_lambdas.yml +26 -0
- data/config/default_params.yml +303 -0
- data/config/default_params.yml.example +124 -0
- data/config/default_services.yml +62 -0
- data/ext/common_helper.rb +21 -0
- data/ext/config/managed_policies.yml +156 -0
- data/ext/helper.rb +29 -0
- data/ext/policies.rb +53 -0
- data/ext/zip_helper.rb +57 -0
- data/lambdas/acm_issuer_validator/lib/install.sh +20 -0
- data/templates/bastion.rb +121 -0
- data/templates/ciinabox.rb +159 -0
- data/templates/ecs-cluster.rb +252 -0
- data/templates/ecs-services.rb +340 -0
- data/templates/lambdas.rb +172 -0
- data/templates/services/bitbucket.rb +81 -0
- data/templates/services/drone.rb +394 -0
- data/templates/services/hawtio.rb +100 -0
- data/templates/services/icinga2.rb +79 -0
- data/templates/services/jenkins.rb +209 -0
- data/templates/services/nexus.rb +96 -0
- data/templates/vpc.rb +290 -0
- metadata +144 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
#Sample file of what your params.yml file should include
|
2
|
+
|
3
|
+
#ciinabox default config
|
4
|
+
ciinabox_version: 0.1
|
5
|
+
|
6
|
+
ciinabox_name: example
|
7
|
+
|
8
|
+
aws_profile: example
|
9
|
+
|
10
|
+
aws_region: us-east-1
|
11
|
+
|
12
|
+
aws_account_id: 198712987398
|
13
|
+
|
14
|
+
#override S3 bucket location
|
15
|
+
source_bucket: source.aws.example.com
|
16
|
+
|
17
|
+
#add if you want ecs docker volume != 22GB - must be > 22
|
18
|
+
#ecs_docker_volume_size: 100
|
19
|
+
|
20
|
+
#use this to change volume snapshot for running ciinabox
|
21
|
+
#ecs_data_volume_name: "ECSDataVolume2s"
|
22
|
+
|
23
|
+
#set the size of the ecs data volume -- NOTE: would take a new volume - i.e. change volume name
|
24
|
+
#ecs_data_volume_size: 250
|
25
|
+
|
26
|
+
#set the snapshot to restore from
|
27
|
+
#ecs_data_volume_snapshot: snap-49e2b3b5
|
28
|
+
|
29
|
+
#optional ciinabox name if you need more than one or you want a different name
|
30
|
+
#stack_name: ciinabox-tools
|
31
|
+
|
32
|
+
#for internal elb for jenkins
|
33
|
+
#internal_elb: false
|
34
|
+
|
35
|
+
#ciinabox ECS cluster name
|
36
|
+
cluster_name: ciinabox
|
37
|
+
|
38
|
+
#log level - change to :debug to see the AWS commands being executed
|
39
|
+
log_level: :info
|
40
|
+
|
41
|
+
#change this to your own dns_domain
|
42
|
+
#domain needs to be manage via route53 since the cloudformation adds additional records
|
43
|
+
dns_domain: tools.aws.example.com
|
44
|
+
|
45
|
+
#icinga2_image: AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION/base2/icinga2:VERSION_TAG
|
46
|
+
|
47
|
+
#AWS Availability Zones Idenifers
|
48
|
+
availability_zones:
|
49
|
+
- 'A'
|
50
|
+
- 'B'
|
51
|
+
|
52
|
+
azId:
|
53
|
+
A: 0
|
54
|
+
B: 1
|
55
|
+
C: 2
|
56
|
+
D: 3
|
57
|
+
E: 4
|
58
|
+
|
59
|
+
#ciinabox environment config
|
60
|
+
Mappings:
|
61
|
+
EnvironmentType:
|
62
|
+
ciinabox:
|
63
|
+
KeyName: ciinabox
|
64
|
+
SSLCertARN: "arn:aws:iam::198712987398:server-certificate/ciinabox"
|
65
|
+
NetworkPrefix: 10
|
66
|
+
StackOctet: 150
|
67
|
+
StackMask: 16
|
68
|
+
SubnetMask: 26
|
69
|
+
NatInstanceType: t2.micro
|
70
|
+
ECSInstanceType: t2.large
|
71
|
+
|
72
|
+
#Subnet offsets 10.150.x.0/26
|
73
|
+
vpc:
|
74
|
+
SubnetOctetA: "0"
|
75
|
+
SubnetOctetB: "1"
|
76
|
+
ecs:
|
77
|
+
SubnetOctetA: "2"
|
78
|
+
SubnetOctetB: "3"
|
79
|
+
|
80
|
+
#Amazon Linux AMI 2015.03.1 (HVM), SSD Volume Type
|
81
|
+
natAMI:
|
82
|
+
us-east-1:
|
83
|
+
ami: ami-60b6c60a
|
84
|
+
us-west-2:
|
85
|
+
ami: ami-f0091d91
|
86
|
+
ap-southeast-2:
|
87
|
+
ami: ami-48d38c2b
|
88
|
+
eu-west-1:
|
89
|
+
ami: ami-bff32ccc
|
90
|
+
|
91
|
+
ecs_ami:
|
92
|
+
us-east-1:
|
93
|
+
ami: ami-cb2305a1
|
94
|
+
us-west-2:
|
95
|
+
ami: ami-ec75908c
|
96
|
+
ap-southeast-2:
|
97
|
+
ami: ami-83af8ae0
|
98
|
+
eu-west-1:
|
99
|
+
ami: ami-13f84d60
|
100
|
+
|
101
|
+
#Environment Access
|
102
|
+
#add list of public IP addresses you want to access the environment from
|
103
|
+
#default to public access probably best to change this
|
104
|
+
opsAccess:
|
105
|
+
- 44.33.123.223/32
|
106
|
+
|
107
|
+
#add list of public IP addresses for your developers to access the environment
|
108
|
+
#default to public access probably best to change this
|
109
|
+
devAccess:
|
110
|
+
- 213.120.111.2/32 #Example
|
111
|
+
|
112
|
+
# Upload a default ssl cert to AWS to be used by default to ciinabox service ELBs
|
113
|
+
default_ssl_cert_id: "arn:aws:iam::198712987398:server-certificate/ciinabox"
|
114
|
+
|
115
|
+
|
116
|
+
#extra_stacks:
|
117
|
+
# elk:
|
118
|
+
# #define template name? - optional
|
119
|
+
# file_name: elk
|
120
|
+
# parameters:
|
121
|
+
# RoleName: search
|
122
|
+
# CertName: x
|
123
|
+
# SubnetOctetA: 11
|
124
|
+
# SubnetOctetB: 12
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# ciinabox services default configuration
|
2
|
+
|
3
|
+
services:
|
4
|
+
- jenkins:
|
5
|
+
# Optional Jenkins Service Parameters
|
6
|
+
# ContainerImage: base2/ciinabox-jenkins:2.0
|
7
|
+
# ContainerMemory: 4096
|
8
|
+
# ContainerCPU: 300
|
9
|
+
# JAVA_OPTS: -Xmx4096m
|
10
|
+
# you only need to add these ports for JNLP slaves
|
11
|
+
# LoadBalancerPort: 50000
|
12
|
+
# InstancePort: 50000
|
13
|
+
# Protocol: TCP
|
14
|
+
|
15
|
+
#example for Internal Port for Jenkins
|
16
|
+
# - jenkins:
|
17
|
+
# LoadBalancerPort: 50000
|
18
|
+
# InstancePort: 50000
|
19
|
+
# Protocol: TCP
|
20
|
+
# needs internal_elb: true
|
21
|
+
# will trigger this 2nd hostname for jenkins internal-jenkins.#{dns_domain}
|
22
|
+
|
23
|
+
#example for drone
|
24
|
+
# - drone:
|
25
|
+
# params:
|
26
|
+
# -
|
27
|
+
# VPC:
|
28
|
+
# Ref: VPC
|
29
|
+
# -
|
30
|
+
# SubnetPublicA:
|
31
|
+
# Ref: SubnetPublicA
|
32
|
+
# -
|
33
|
+
# SubnetPublicB:
|
34
|
+
# Ref: SubnetPublicB
|
35
|
+
# -
|
36
|
+
# ECSSubnetPrivateA:
|
37
|
+
# Ref: ECSSubnetPrivateA
|
38
|
+
# -
|
39
|
+
# ECSSubnetPrivateB:
|
40
|
+
# Ref: ECSSubnetPrivateB
|
41
|
+
# -
|
42
|
+
# SecurityGroupBackplane:
|
43
|
+
# Ref: SecurityGroupBackplane
|
44
|
+
# -
|
45
|
+
# SecurityGroupOps:
|
46
|
+
# Ref: SecurityGroupOps
|
47
|
+
# -
|
48
|
+
# SecurityGroupDev:
|
49
|
+
# Ref: SecurityGroupDev
|
50
|
+
# -
|
51
|
+
# SecurityGroupNatGateway:
|
52
|
+
# Ref: SecurityGroupNatGateway
|
53
|
+
# -
|
54
|
+
# SecurityGroupWebHooks:
|
55
|
+
# Ref: SecurityGroupWebHooks
|
56
|
+
# -
|
57
|
+
# ECSENIPrivateIpAddress:
|
58
|
+
# Ref: ECSENIPrivateIpAddress
|
59
|
+
# tasks:
|
60
|
+
# drone-server:
|
61
|
+
# env:
|
62
|
+
# DRONE_OPEN: true
|
@@ -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,156 @@
|
|
1
|
+
ec2-describe:
|
2
|
+
action:
|
3
|
+
- ec2:Describe*
|
4
|
+
- autoscaling:Describe*
|
5
|
+
- elasticloadbalancing:Describe*
|
6
|
+
|
7
|
+
cloudwatch-logs:
|
8
|
+
action:
|
9
|
+
- logs:CreateLogGroup
|
10
|
+
- logs:CreateLogStream
|
11
|
+
- logs:PutLogEvents
|
12
|
+
- logs:DescribeLogStreams
|
13
|
+
- logs:DescribeLogGroups
|
14
|
+
resource:
|
15
|
+
- arn:aws:logs:*:*:*
|
16
|
+
|
17
|
+
cloudwatch-monitoring:
|
18
|
+
action:
|
19
|
+
- cloudwatch:PutMetricData
|
20
|
+
- cloudwatch:GetMetricStatistics
|
21
|
+
- cloudwatch:ListMetrics
|
22
|
+
|
23
|
+
s3-list-buckets:
|
24
|
+
action:
|
25
|
+
- s3:ListAllMyBuckets
|
26
|
+
- s3:ListBucket
|
27
|
+
|
28
|
+
s3-chef-ro:
|
29
|
+
action:
|
30
|
+
- s3:Get*
|
31
|
+
- s3:List*
|
32
|
+
resource:
|
33
|
+
- arn:aws:s3:::%{source_bucket}/chef
|
34
|
+
- arn:aws:s3:::%{source_bucket}/chef/*
|
35
|
+
|
36
|
+
s3-environment-ro:
|
37
|
+
action:
|
38
|
+
- s3:Get*
|
39
|
+
- s3:List*
|
40
|
+
resource:
|
41
|
+
- arn:aws:s3:::%{source_bucket}/chef-environments
|
42
|
+
- arn:aws:s3:::%{source_bucket}/chef-environments/*
|
43
|
+
|
44
|
+
s3-codedeploy-ro:
|
45
|
+
action:
|
46
|
+
- s3:Get*
|
47
|
+
- s3:List*
|
48
|
+
resource:
|
49
|
+
- arn:aws:s3:::%{source_bucket}/codedeploy
|
50
|
+
- arn:aws:s3:::%{source_bucket}/codedeploy/*
|
51
|
+
|
52
|
+
ecs-service-role:
|
53
|
+
action:
|
54
|
+
- ecs:CreateCluster
|
55
|
+
- ecs:DeregisterContainerInstance
|
56
|
+
- ecs:DiscoverPollEndpoint
|
57
|
+
- ecs:Poll
|
58
|
+
- ecs:RegisterContainerInstance
|
59
|
+
- ecs:StartTelemetrySession
|
60
|
+
- ecs:Submit*
|
61
|
+
- ec2:AuthorizeSecurityGroupIngress
|
62
|
+
- ec2:Describe*
|
63
|
+
- elasticloadbalancing:DeregisterInstancesFromLoadBalancer
|
64
|
+
- elasticloadbalancing:Describe*
|
65
|
+
- elasticloadbalancing:RegisterInstancesWithLoadBalancer
|
66
|
+
- autoscaling:Describe*
|
67
|
+
|
68
|
+
ecr-pull-images:
|
69
|
+
action:
|
70
|
+
- ecr:BatchCheckLayerAvailability
|
71
|
+
- ecr:BatchGetImage
|
72
|
+
- ecr:Get*
|
73
|
+
- ecr:List*
|
74
|
+
|
75
|
+
attach-ebs-volume:
|
76
|
+
action:
|
77
|
+
- ec2:DescribeVolumes
|
78
|
+
- ec2:AttachVolume
|
79
|
+
- ec2:DetachVolume
|
80
|
+
|
81
|
+
attach-network-interface:
|
82
|
+
action:
|
83
|
+
- ec2:DescribeNetworkInterfaces
|
84
|
+
- ec2:AttachNetworkInterface
|
85
|
+
- ec2:DetachNetworkInterface
|
86
|
+
|
87
|
+
associate-address:
|
88
|
+
action:
|
89
|
+
- ec2:AssociateAddress
|
90
|
+
|
91
|
+
ssm:
|
92
|
+
action:
|
93
|
+
- ssm:DescribeAssociation
|
94
|
+
- ssm:GetDeployablePatchSnapshotForInstance
|
95
|
+
- ssm:GetDocument
|
96
|
+
- ssm:GetParameters
|
97
|
+
- ssm:ListAssociations
|
98
|
+
- ssm:ListInstanceAssociations
|
99
|
+
- ssm:PutInventory
|
100
|
+
- ssm:UpdateAssociationStatus
|
101
|
+
- ssm:UpdateInstanceAssociationStatus
|
102
|
+
- ssm:UpdateInstanceInformation
|
103
|
+
|
104
|
+
ec2messages:
|
105
|
+
action:
|
106
|
+
- ec2messages:AcknowledgeMessage
|
107
|
+
- ec2messages:DeleteMessage
|
108
|
+
- ec2messages:FailMessage
|
109
|
+
- ec2messages:GetEndpoint
|
110
|
+
- ec2messages:GetMessages
|
111
|
+
- ec2messages:SendReply
|
112
|
+
|
113
|
+
s3-secrets-ro:
|
114
|
+
action:
|
115
|
+
- s3:Get*
|
116
|
+
- s3:List*
|
117
|
+
resource:
|
118
|
+
- Fn::Join:
|
119
|
+
- ""
|
120
|
+
-
|
121
|
+
- 'arn:aws:s3:::'
|
122
|
+
- Fn::FindInMap:
|
123
|
+
- 'Secrets'
|
124
|
+
- Ref: 'EnvironmentType'
|
125
|
+
- 'bucket'
|
126
|
+
- '/'
|
127
|
+
- Fn::FindInMap:
|
128
|
+
- 'Secrets'
|
129
|
+
- Ref: 'EnvironmentType'
|
130
|
+
- 'key'
|
131
|
+
- '/'
|
132
|
+
- Ref: "EnvironmentName"
|
133
|
+
- '/*'
|
134
|
+
|
135
|
+
route53-manage-records:
|
136
|
+
action:
|
137
|
+
- route53:ListTagsForResources
|
138
|
+
- route53:GetHostedZone
|
139
|
+
- route53:ListHostedZones
|
140
|
+
- route53:ListHostedZonesByName
|
141
|
+
- route53:ChangeResourceRecordSets
|
142
|
+
- route53:ListResourceRecordSets
|
143
|
+
- route53:ListTagsForResource
|
144
|
+
|
145
|
+
acm-cert-issue:
|
146
|
+
action:
|
147
|
+
- acm:DeleteCertificate
|
148
|
+
- acm:DescribeCertificate
|
149
|
+
- acm:DescribeCertificate
|
150
|
+
- acm:RequestCertificate
|
151
|
+
- acm:ListCertificates
|
152
|
+
|
153
|
+
lambda-invoke:
|
154
|
+
action:
|
155
|
+
- lambda:Get*
|
156
|
+
- lambda:Invoke*
|
data/ext/helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# ciinabox cfndsl helpers
|
2
|
+
def add_security_group_rules (access_list)
|
3
|
+
rules = []
|
4
|
+
access_list.each do |ip|
|
5
|
+
rules << { IpProtocol: 'tcp', FromPort: '22', ToPort: '22', CidrIp: ip }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def nat_scale_up_schedule(scale_up_schedule)
|
10
|
+
expr = scale_up_schedule.split
|
11
|
+
hour = expr[1].to_i
|
12
|
+
minute = expr[0].to_i
|
13
|
+
if minute < 10
|
14
|
+
minute = 60 + minute - 10
|
15
|
+
hour = hour - 1
|
16
|
+
else
|
17
|
+
minute = minute - 10
|
18
|
+
end
|
19
|
+
return "#{minute} #{hour} #{expr[2]} #{expr[3]} #{expr[4]}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def lookup_service(name, services=[])
|
23
|
+
services.each do |service|
|
24
|
+
if service.has_key? name
|
25
|
+
return service[name]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
data/ext/policies.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Configs
|
4
|
+
class << self; attr_accessor :managed_policies, :all end
|
5
|
+
script_dir = File.expand_path File.dirname(__FILE__)
|
6
|
+
@managed_policies = YAML.load(File.read("#{script_dir}/config/managed_policies.yml"))
|
7
|
+
@all = Hash.new.tap { |h| Dir['config/*.yml'].each { |yml| h.merge!(YAML.load(File.open(yml))) }}
|
8
|
+
# Override with ciinabox configs
|
9
|
+
ciinaboxes_dir = ENV['CIINABOXES_DIR'] || 'ciinaboxes'
|
10
|
+
ciinabox_name = ENV['CIINABOX'] || ''
|
11
|
+
(Dir["#{ciinaboxes_dir}/#{ciinabox_name}/config/*.yml"]).each { |yml|
|
12
|
+
@all.merge!(YAML.load(File.open(yml)))
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
class Policies
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@policy_array = Array.new
|
20
|
+
@config = Configs.all
|
21
|
+
@policies = (@config.key?('custom_policies') ? Configs.managed_policies.merge(@config['custom_policies']) : Configs.managed_policies)
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_policies(group = nil)
|
25
|
+
create_policies(@config['default_policies']) if @config.key?('default_policies')
|
26
|
+
create_policies(@config['group_policies'][group]) unless group.nil?
|
27
|
+
return @policy_array
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_policies(policies)
|
31
|
+
policies.each do |policy|
|
32
|
+
raise "ERROR: #{policy} policy doesn't exist in the managed policies or as a custom policy" unless @policies.key?(policy)
|
33
|
+
resource = (@policies[policy].key?('resource') ? gsub_yml(@policies[policy]['resource']) : ["*"])
|
34
|
+
@policy_array << { PolicyName: policy, PolicyDocument: { Statement: [ { Effect:"Allow", Action: @policies[policy]['action'], Resource: resource }]} }
|
35
|
+
end
|
36
|
+
return @policy_array
|
37
|
+
end
|
38
|
+
|
39
|
+
# replaces %{variables} in the yml
|
40
|
+
def gsub_yml(resource)
|
41
|
+
replaced = []
|
42
|
+
resource.each { |r|
|
43
|
+
if r.is_a? String
|
44
|
+
replaced << r.gsub('%{source_bucket}', @config['source_bucket'])
|
45
|
+
else
|
46
|
+
replaced << r
|
47
|
+
end
|
48
|
+
}
|
49
|
+
|
50
|
+
return replaced
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|