aws_pocketknife 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +1 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +115 -0
  11. data/Rakefile +22 -0
  12. data/aws_pocketknife.gemspec +40 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/cert/ca-bundle.crt +3988 -0
  16. data/exe/pocketknife +5 -0
  17. data/lib/aws_pocketknife.rb +88 -0
  18. data/lib/aws_pocketknife/admin/policies/developer_dev_acc.json +10 -0
  19. data/lib/aws_pocketknife/admin/policies/developer_prd_acc.json +15 -0
  20. data/lib/aws_pocketknife/admin/policies/tc_devops.json.erb +207 -0
  21. data/lib/aws_pocketknife/admin/policies/tester_dev_acc.json +176 -0
  22. data/lib/aws_pocketknife/admin/policies/tester_prd_acc.json +176 -0
  23. data/lib/aws_pocketknife/admin/policies/web_front_end.json.erb +59 -0
  24. data/lib/aws_pocketknife/admin/trust_relationships/ec2.json +13 -0
  25. data/lib/aws_pocketknife/asg.rb +56 -0
  26. data/lib/aws_pocketknife/cli/ami.rb +24 -0
  27. data/lib/aws_pocketknife/cli/asg.rb +40 -0
  28. data/lib/aws_pocketknife/cli/eb.rb +49 -0
  29. data/lib/aws_pocketknife/cli/ec2.rb +61 -0
  30. data/lib/aws_pocketknife/cli/elb.rb +20 -0
  31. data/lib/aws_pocketknife/cli/iam.rb +31 -0
  32. data/lib/aws_pocketknife/cli/main.rb +34 -0
  33. data/lib/aws_pocketknife/cli/rds.rb +13 -0
  34. data/lib/aws_pocketknife/cli/rds_snapshot.rb +44 -0
  35. data/lib/aws_pocketknife/cli/route53.rb +56 -0
  36. data/lib/aws_pocketknife/cloudwatch_logs.rb +25 -0
  37. data/lib/aws_pocketknife/common/logging.rb +31 -0
  38. data/lib/aws_pocketknife/common/utils.rb +63 -0
  39. data/lib/aws_pocketknife/ec2.rb +308 -0
  40. data/lib/aws_pocketknife/elastic_beanstalk.rb +62 -0
  41. data/lib/aws_pocketknife/elb.rb +25 -0
  42. data/lib/aws_pocketknife/iam.rb +135 -0
  43. data/lib/aws_pocketknife/rds.rb +84 -0
  44. data/lib/aws_pocketknife/route53.rb +234 -0
  45. data/lib/aws_pocketknife/tasks/asg.rake +18 -0
  46. data/lib/aws_pocketknife/tasks/cloudwatch.rake +12 -0
  47. data/lib/aws_pocketknife/tasks/ec2.rake +57 -0
  48. data/lib/aws_pocketknife/tasks/elastic_beanstalk.rake +25 -0
  49. data/lib/aws_pocketknife/tasks/elb.rake +13 -0
  50. data/lib/aws_pocketknife/tasks/iam.rake +57 -0
  51. data/lib/aws_pocketknife/tasks/route53.rake +64 -0
  52. data/lib/aws_pocketknife/version.rb +3 -0
  53. metadata +284 -0
@@ -0,0 +1,62 @@
1
+ require 'aws_pocketknife'
2
+
3
+ module AwsPocketknife
4
+ module ElasticBeanstalk
5
+
6
+ class << self
7
+ include AwsPocketknife::Common::Utils
8
+
9
+ def describe_environment_resources(environment_name: '')
10
+ elastic_beanstalk_client.describe_environment_resources({
11
+ environment_name: environment_name,
12
+ })
13
+ end
14
+
15
+ def list_environments()
16
+ describe_environment
17
+ end
18
+
19
+ def describe_environment(environment_name: '')
20
+ resp = nil
21
+ if environment_name.length == 0
22
+ resp = elastic_beanstalk_client.describe_environments({})
23
+ else
24
+ environment_list = environment_name.split(";")
25
+ resp = elastic_beanstalk_client.describe_environments({
26
+ environment_names: environment_list,
27
+ })
28
+ end
29
+
30
+ resp[:environments]
31
+ end
32
+
33
+ def list_environment_variables(environment_name: '')
34
+
35
+ #get application name
36
+ environment = describe_environment(environment_name: environment_name)[0]
37
+ app_name = environment.application_name
38
+
39
+ #get environment_variables
40
+ resp = elastic_beanstalk_client.describe_configuration_settings({
41
+ application_name: app_name,
42
+ environment_name: environment_name,
43
+ })
44
+
45
+ configuration_setting = resp.configuration_settings[0]
46
+ option_settings = configuration_setting.option_settings
47
+ environment_variables = []
48
+ option_settings.each do |option|
49
+ if option.option_name == "EnvironmentVariables"
50
+ environment_variables = option.value.split(",")
51
+ break
52
+ end
53
+ end
54
+
55
+ environment_variables
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,25 @@
1
+ require 'aws_pocketknife'
2
+
3
+ module AwsPocketknife
4
+ module Elb
5
+
6
+ class << self
7
+ include AwsPocketknife::Common::Utils
8
+
9
+ def describe_elb_by_name(name: '')
10
+ resp = elb_client.describe_load_balancers({
11
+ load_balancer_names: [name],
12
+ page_size: 1,
13
+ })
14
+
15
+ if resp.nil? or resp.load_balancer_descriptions.empty?
16
+ return nil
17
+ else
18
+ return resp.load_balancer_descriptions.first
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,135 @@
1
+ require 'erubis'
2
+ require 'aws_pocketknife'
3
+
4
+ module AwsPocketknife
5
+ module Iam
6
+
7
+ class << self
8
+ include AwsPocketknife::Common::Utils
9
+
10
+ def list_ssl_certificates
11
+ iam_client.list_server_certificates({})
12
+ end
13
+
14
+ def create_iam_user(username)
15
+ puts "Creating iam user: #{username}"
16
+ iam_client.create_user({user_name: username})
17
+ puts "Iam user: #{username} created"
18
+ end
19
+
20
+ def create_group(group_name)
21
+ puts "Creating group: #{group_name}"
22
+ iam_client.create_group({group_name: group_name})
23
+ puts "Created group: #{group_name}"
24
+ end
25
+
26
+ def create_policy(policy_name, policy)
27
+ puts "Creating policy: #{policy_name}"
28
+ iam_client.create_policy({policy_name: policy_name,policy_document: policy})
29
+ puts "Created policy: #{policy_name}"
30
+ end
31
+
32
+ def create_policy_from_policy_file(policy_name: "", policy_file: "", s3_buckets: "")
33
+ puts "Creating policy #{policy_name} from saved policy #{policy_file}"
34
+ policy = IO.read(policy_file)
35
+ buckets = get_bucket_list(buckets_list: s3_buckets)
36
+ template = Erubis::Eruby.new(policy)
37
+ vars = {buckets: buckets}
38
+
39
+ policy = template.result(vars)
40
+
41
+ puts policy
42
+
43
+ unless (policy.nil?)
44
+ iam_client.create_policy({policy_name: policy_name, policy_document: policy})
45
+ else
46
+ puts 'Policy not found'
47
+ end
48
+ puts "Created Policy #{policy_name}"
49
+ end
50
+
51
+ def attach_policy_to_group(policy_name, group_name )
52
+ puts "Attaching policy #{policy_name} to group #{group_name}"
53
+ arn_number = get_policy_arn(policy_name)
54
+
55
+ unless arn_number.nil?
56
+ iam_client.attach_group_policy(group_name: group_name, policy_arn: arn_number)
57
+ else
58
+ puts "The policy #{policy_name} could not be found"
59
+ end
60
+ puts "Policy #{policy_name} attached to group #{group_name}"
61
+ end
62
+
63
+ def add_user_to_group(username,group_name)
64
+ puts "Attaching user: #{username} to group: #{group_name}"
65
+ iam_client.add_user_to_group(group_name: group_name, user_name: username)
66
+ puts "User: #{username} attached to group: #{group_name}"
67
+
68
+ end
69
+
70
+ def create_role(role_name, trust_relationship_file)
71
+ begin
72
+ if File.exist?(trust_relationship_file)
73
+ trust_relationship = IO.read(trust_relationship_file)
74
+ unless trust_relationship.nil?
75
+ puts "Creating role: #{role_name} with trust relationship #{trust_relationship}"
76
+ iam_client.create_role(role_name: role_name, assume_role_policy_document: trust_relationship)
77
+ puts "Created role: #{role_name} with trust relationship #{trust_relationship}"
78
+ else
79
+ raise "Trust Relationship file could not be loaded"
80
+ end
81
+ else
82
+ raise "Trust Relationship file could not be loaded"
83
+ end
84
+ rescue Exception => e
85
+ puts e
86
+ raise e
87
+ end
88
+ end
89
+
90
+ def attach_policy_to_role(role_name, policy_name)
91
+ arn_number = get_policy_arn(policy_name)
92
+ unless arn_number.nil?
93
+ puts "Attach policy: #{policy_name} to role: #{role_name}"
94
+ iam_client.attach_role_policy(role_name: role_name, policy_arn: arn_number)
95
+ puts "Attached policy: #{policy_name} to role: #{role_name}"
96
+ else
97
+ raise "The policy #{policy_name} could not be found"
98
+ end
99
+ end
100
+
101
+ def create_instance_profile(instance_profile_name)
102
+ puts "Creating instance profile: #{instance_profile_name}"
103
+ iam_client.create_instance_profile(instance_profile_name: instance_profile_name)
104
+ puts "Created instance profile: #{instance_profile_name}"
105
+ end
106
+
107
+ def add_role_to_instance_profile(role_name,instance_profile_name)
108
+ puts "Adding role #{role_name} to instance profile: #{instance_profile_name}"
109
+ iam_client.add_role_to_instance_profile(instance_profile_name: instance_profile_name, role_name: role_name)
110
+ puts "Added role #{role_name} to instance profile: #{instance_profile_name}"
111
+ end
112
+
113
+
114
+ private
115
+
116
+ def get_bucket_list(buckets_list: "")
117
+ buckets_list.strip.split(";")
118
+ end
119
+
120
+ def get_policy_arn(policy_name)
121
+ response = iam_client.list_policies({scope: 'Local'})
122
+ arn_number = nil
123
+ response.policies.each do |value|
124
+ if value.policy_name == policy_name
125
+ arn_number = value.arn
126
+ break;
127
+ end
128
+ end
129
+ arn_number
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+ end
@@ -0,0 +1,84 @@
1
+ require 'aws_pocketknife'
2
+
3
+ module AwsPocketknife
4
+ module Rds
5
+
6
+ AVAILABLE = 'available'.freeze
7
+ CREATING = 'creating'.freeze
8
+ DELETING = 'deleting'.freeze
9
+
10
+ class << self
11
+ include AwsPocketknife::Common::Utils
12
+
13
+ def describe_snapshots(options)
14
+ db_name = options.fetch(:db_name, '')
15
+ rds_client.describe_db_snapshots({db_instance_identifier: db_name}).db_snapshots
16
+ end
17
+
18
+ # creates snapshot for the database name
19
+ def create_snapshot(options)
20
+ db_name = options.fetch(:db_name, 'my-snapshot')
21
+ snapshot_name = get_snapshot_name(db_name)
22
+ rds_client.create_db_snapshot(db_instance_identifier: db_name, db_snapshot_identifier: snapshot_name)
23
+
24
+ Retryable.retryable(:tries => 15, :sleep => lambda { |n| 2**n }, :on => StandardError) do |retries, exception|
25
+ response = rds_client.describe_db_snapshots(db_snapshot_identifier: snapshot_name)
26
+
27
+ snapshot = response.db_snapshots.find { |s| s.db_snapshot_identifier == snapshot_name }
28
+ status = snapshot.status
29
+ percent_progress = snapshot.percent_progress
30
+ puts "RDS Snapshot #{snapshot_name} status: #{status}, progress #{percent_progress}%"
31
+ raise StandardError if status != AwsPocketknife::Rds::AVAILABLE
32
+ end
33
+
34
+ end
35
+
36
+ def get_snapshot_name(db_name)
37
+ now_str = Time.now.strftime('%Y-%m-%d-%H-%M')
38
+ "#{db_name}-#{now_str}"
39
+ end
40
+
41
+ def clean_snapshots(options)
42
+ puts "options: #{options}"
43
+
44
+ db_name = options.fetch(:db_name, '')
45
+ days = options.fetch(:days, '30').to_i * 24 * 3600
46
+ dry_run = options.fetch(:dry_run, true)
47
+
48
+ creation_time = Time.now - days
49
+ puts "Cleaning up MANUAL snapshots older than #{days} days, i.e, with creation_time < #{creation_time} for db [#{db_name}]"
50
+
51
+ snapshots_to_remove = []
52
+ snapshots = describe_snapshots options
53
+ snapshots.each do |snapshot|
54
+ snapshot.snapshot_create_time.is_a?(String) ? snapshot_creation_time = Time.parse(snapshot.snapshot_create_time) : snapshot_creation_time = snapshot.snapshot_create_time
55
+
56
+ msg = "Snapshot #{snapshot.db_snapshot_identifier} (type=#{snapshot.snapshot_type}) (snapshot_creation_time: #{snapshot_creation_time}) > (#{creation_time})? "
57
+ if creation_time <= snapshot_creation_time
58
+ if (snapshot.snapshot_type == 'manual')
59
+ snapshots_to_remove << snapshot
60
+ msg << " YES, marking to be deleted"
61
+ else
62
+ msg << " NO"
63
+ end
64
+ else
65
+ msg << "NO (is not a manual snapshot)"
66
+ end
67
+ puts msg
68
+ end
69
+
70
+ puts "snapshots_to_remove: #{snapshots_to_remove.map { |s| s.db_snapshot_identifier}}"
71
+
72
+ unless dry_run
73
+ snapshots_to_remove.each do |snapshot|
74
+ puts "Removing snapshot #{snapshot.db_snapshot_identifier} (status=#{snapshot.status})"
75
+ rds_client.delete_db_snapshot({db_snapshot_identifier:snapshot.db_snapshot_identifier})
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,234 @@
1
+ require 'aws_pocketknife'
2
+
3
+ module AwsPocketknife
4
+ module Route53
5
+
6
+ class << self
7
+ include AwsPocketknife::Common::Utils
8
+
9
+ Logging = Common::Logging.logger
10
+
11
+ def list_hosted_zones
12
+ result = route53_client.list_hosted_zones
13
+ unless result.nil?
14
+ return result.hosted_zones
15
+ else
16
+ return []
17
+ end
18
+ end
19
+
20
+ def describe_hosted_zone(hosted_zone: "")
21
+ hosted_zones = list_hosted_zones
22
+ zone = find_hosted_zone_id(list: hosted_zones, name: hosted_zone)
23
+ end
24
+
25
+ def get_hosted_zone_id_and_origin_record(origin_dns_name, origin_hosted_zone, record_type)
26
+ hosted_zone = describe_hosted_zone(hosted_zone: origin_hosted_zone)
27
+ hosted_zone_id = get_hosted_zone_id(hosted_zone: hosted_zone.id)
28
+
29
+ # get origin record
30
+ origin_record = get_record(hosted_zone_name: origin_hosted_zone,
31
+ record_name: origin_dns_name,
32
+ record_type: record_type)
33
+
34
+ if origin_record.empty?
35
+ Logging.warn "Could not find record for #{origin_dns_name} at #{origin_hosted_zone}"
36
+ end
37
+ return hosted_zone_id, origin_record
38
+ end
39
+
40
+
41
+ def update_record(origin_hosted_zone: "",
42
+ origin_dns_name: "",
43
+ record_type: "A",
44
+ destiny_dns_name:"",
45
+ destiny_hosted_zone: ""
46
+ )
47
+
48
+
49
+ puts "Updating #{origin_dns_name} at #{origin_hosted_zone} with #{destiny_dns_name} at #{destiny_hosted_zone}"
50
+ if destiny_hosted_zone.empty?
51
+ return update_cname_record(origin_hosted_zone: origin_hosted_zone,
52
+ origin_dns_name: origin_dns_name,
53
+ destiny_dns_name:destiny_dns_name,
54
+ destiny_hosted_zone: destiny_hosted_zone
55
+ )
56
+ else
57
+ return update_record_from_existing_dns_entry(origin_hosted_zone: origin_hosted_zone,
58
+ origin_dns_name: origin_dns_name,
59
+ record_type: record_type,
60
+ destiny_dns_name:destiny_dns_name,
61
+ destiny_hosted_zone: destiny_hosted_zone
62
+ )
63
+ end
64
+
65
+
66
+ end
67
+
68
+ def get_payload_for_record_update(change: "", hosted_zone_id: "")
69
+ {
70
+ hosted_zone_id: hosted_zone_id,
71
+ change_batch: {
72
+ comment: "",
73
+ changes: [change]
74
+ }
75
+
76
+ }
77
+ end
78
+
79
+ def get_record(hosted_zone_name: "", record_name: "", record_type: "")
80
+ record = []
81
+ records = list_records_for_zone_name(
82
+ hosted_zone_name: hosted_zone_name,
83
+ record_name:record_name,
84
+ record_type: record_type)
85
+
86
+ records.each do |r|
87
+ return [r] if r.name == record_name
88
+ end
89
+
90
+ return record
91
+ end
92
+
93
+ def list_records_for_zone_name(hosted_zone_name: "", record_name: "", record_type: "")
94
+ records = []
95
+ hosted_zone = describe_hosted_zone(hosted_zone: hosted_zone_name)
96
+ return records if hosted_zone.nil?
97
+
98
+ hosted_zone_id = get_hosted_zone_id(hosted_zone: hosted_zone.id)
99
+
100
+ result = nil
101
+ if record_name.length != 0 and record_type != 0
102
+ result = route53_client.list_resource_record_sets({hosted_zone_id: hosted_zone_id,
103
+ start_record_name: record_name,
104
+ start_record_type: record_type, # accepts SOA, A, TXT, NS, CNAME, MX, PTR, SRV, SPF, AAAA
105
+ max_items: 1,
106
+ })
107
+ else
108
+ result = route53_client.list_resource_record_sets({hosted_zone_id: hosted_zone_id})
109
+ end
110
+ result.resource_record_sets.each do |record|
111
+ if ["A", "CNAME", "AAAA"].include?record.type
112
+ records << record
113
+ end
114
+ end
115
+ return records
116
+ end
117
+
118
+ def get_hosted_zone_id(hosted_zone: "")
119
+ hosted_zone.split("/").reverse[0]
120
+ end
121
+
122
+ private
123
+
124
+ def update_cname_record(origin_hosted_zone: "",
125
+ origin_dns_name: "",
126
+ record_type: "CNAME",
127
+ destiny_dns_name:"",
128
+ destiny_hosted_zone: ""
129
+ )
130
+
131
+ hosted_zone_id, origin_record = get_hosted_zone_id_and_origin_record(origin_dns_name, origin_hosted_zone, record_type)
132
+
133
+ new_dns_name = destiny_dns_name
134
+ origin_record = origin_record[0]
135
+
136
+ if not origin_record.alias_target.nil? and new_dns_name == origin_record.alias_target.dns_name
137
+ Logging.info "Origin and destiny alias_target.dns_name are the same: #{new_dns_name} Aborting..."
138
+ return false
139
+ elsif origin_record.resource_records.length != 0 and new_dns_name == origin_record.resource_records[0].value
140
+ Loggin.info "Origin and destiny alias_target.dns_name are the same: #{new_dns_name} Aborting..."
141
+ return false
142
+ end
143
+
144
+ change = {
145
+ action: "UPSERT",
146
+ resource_record_set: {
147
+ name: origin_dns_name,
148
+ type: record_type,
149
+ ttl: 300,
150
+ resource_records: [{value: new_dns_name}]
151
+ }
152
+ }
153
+
154
+ payload = get_payload_for_record_update(change: change, hosted_zone_id: hosted_zone_id)
155
+
156
+ nice_print(object: payload)
157
+ result = route53_client.change_resource_record_sets(payload)
158
+
159
+ end
160
+
161
+ def update_record_from_existing_dns_entry(origin_hosted_zone: "",
162
+ origin_dns_name: "",
163
+ record_type: "A",
164
+ destiny_dns_name:"",
165
+ destiny_hosted_zone: ""
166
+ )
167
+
168
+ # get hosted zone
169
+ hosted_zone_id, origin_record = get_hosted_zone_id_and_origin_record(origin_dns_name, origin_hosted_zone, record_type)
170
+
171
+
172
+ # get record for new dns name
173
+ destiny_record = get_record(hosted_zone_name: destiny_hosted_zone,
174
+ record_name: destiny_dns_name,
175
+ record_type: record_type)
176
+
177
+ if destiny_record.empty?
178
+ Logging.warn "Could not find destiny record for #{destiny_dns_name} at #{destiny_hosted_zone}"
179
+ return nil
180
+ end
181
+
182
+ if destiny_record[0].alias_target.nil?
183
+ Logging.warn "DNS #{destiny_dns_name} is invalid"
184
+ return nil
185
+ end
186
+
187
+ destiny_hosted_zone_id = destiny_record[0].alias_target.hosted_zone_id
188
+ new_dns_name = destiny_record[0].alias_target.dns_name
189
+ origin_record = origin_record[0]
190
+
191
+ unless new_dns_name.start_with?("dualstack.")
192
+ Logging.info "Adding dualstack. to #{new_dns_name}"
193
+ new_dns_name = "dualstack." + new_dns_name
194
+ end
195
+
196
+ if not origin_record.alias_target.nil? and new_dns_name == origin_record.alias_target.dns_name
197
+ Logging.info "Origin dns and destiny alias_target.dns_name points to the same record: #{new_dns_name}\nAborting..."
198
+ return false
199
+ elsif origin_record.resource_records.length != 0 and new_dns_name == origin_record.resource_records[0].value
200
+ Logging.info "Origin dns and destiny alias_target.dns_name points to the same record: #{new_dns_name}\nAborting..."
201
+ return false
202
+ end
203
+
204
+ change = {
205
+ action: "UPSERT",
206
+ resource_record_set: {
207
+ name: origin_dns_name,
208
+ type: record_type,
209
+ alias_target: {
210
+ hosted_zone_id: destiny_hosted_zone_id, # required
211
+ dns_name: new_dns_name, # required
212
+ evaluate_target_health: false, # required
213
+ }
214
+ }
215
+ }
216
+
217
+ payload = get_payload_for_record_update(change: change, hosted_zone_id: hosted_zone_id)
218
+
219
+ nice_print(object: payload)
220
+ result = route53_client.change_resource_record_sets(payload)
221
+
222
+ end
223
+
224
+ # Recevies a list of hosted zones and returns the element specified in name
225
+ def find_hosted_zone_id(list: nil, name: nil)
226
+ list.each do |h|
227
+ return h if h.name == name
228
+ end
229
+ return nil
230
+ end
231
+ end
232
+
233
+ end
234
+ end