cloud-mu 3.1.6 → 3.4.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 +4 -4
- data/Dockerfile +1 -1
- data/bin/mu-adopt +15 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +37 -1
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +4 -4
- data/cookbooks/mu-tools/attributes/default.rb +7 -0
- data/cookbooks/mu-tools/libraries/helper.rb +87 -3
- data/cookbooks/mu-tools/recipes/apply_security.rb +39 -23
- data/cookbooks/mu-tools/recipes/aws_api.rb +13 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +4 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +33 -12
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/clean-stock-amis +10 -2
- data/extras/generate-stock-images +7 -3
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
- data/modules/mommacat.ru +2 -2
- data/modules/mu.rb +84 -97
- data/modules/mu/adoption.rb +359 -59
- data/modules/mu/cleanup.rb +67 -44
- data/modules/mu/cloud.rb +108 -1754
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +929 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +178 -0
- data/modules/mu/config.rb +122 -80
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +4 -5
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +81 -9
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +30 -34
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +5 -13
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +10 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +13 -17
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +15 -0
- data/modules/mu/groomers/chef.rb +3 -0
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +22 -1
- data/modules/mu/mommacat.rb +71 -26
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +82 -3
- data/modules/mu/mommacat/search.rb +59 -16
- data/modules/mu/mommacat/storage.rb +119 -48
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +248 -62
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +65 -63
- data/modules/mu/providers/aws/database.rb +1747 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +291 -133
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +469 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -78
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +120 -145
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +141 -73
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +4 -1
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +1 -1
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +15 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +2 -2
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +29 -14
- data/modules/mu/{clouds → providers}/google/database.rb +2 -9
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +4 -4
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +2 -2
- data/modules/mu/{clouds → providers}/google/role.rb +46 -35
- data/modules/mu/{clouds → providers}/google/server.rb +26 -11
- data/modules/mu/{clouds → providers}/google/server_pool.rb +11 -11
- data/modules/mu/{clouds → providers}/google/user.rb +32 -22
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +38 -3
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +2 -2
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +126 -98
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
|
@@ -27,8 +27,8 @@ module MU
|
|
|
27
27
|
|
|
28
28
|
# Called automatically by {MU::Deploy#createResources}
|
|
29
29
|
def create
|
|
30
|
-
MU::Cloud::AWS.sns(region: @config['region'], credentials: @config['credentials']).create_topic(name: @mu_name)
|
|
31
30
|
@cloud_id = @mu_name
|
|
31
|
+
MU::Cloud::AWS.sns(region: @config['region'], credentials: @config['credentials']).create_topic(name: @cloud_id)
|
|
32
32
|
MU.log "Created SNS topic #{@mu_name}"
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -36,17 +36,48 @@ module MU
|
|
|
36
36
|
def groom
|
|
37
37
|
if @config['subscriptions']
|
|
38
38
|
@config['subscriptions'].each { |sub|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
if sub['resource'] and !sub['endpoint']
|
|
40
|
+
endpoint_obj = nil
|
|
41
|
+
MU.retrier([], max: 5, wait: 9, loop_if: Proc.new { endpoint_obj.nil? }) {
|
|
42
|
+
endpoint_obj = MU::Config::Ref.get(sub['resource']).kitten(@deploy)
|
|
43
|
+
}
|
|
44
|
+
sub['endpoint'] = endpoint_obj.arn
|
|
45
|
+
end
|
|
46
|
+
subscribe(sub['endpoint'], sub['type'])
|
|
46
47
|
}
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
|
|
51
|
+
# Subscribe something to this SNS topic
|
|
52
|
+
# @param endpoint [String]: The address, identifier, or ARN of the resource being subscribed
|
|
53
|
+
# @param protocol [String]: The protocol being subscribed
|
|
54
|
+
def subscribe(endpoint, protocol)
|
|
55
|
+
self.class.subscribe(arn, endpoint, protocol, region: @config['region'], credentials: @credentials)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Subscribe something to an SNS topic
|
|
59
|
+
# @param cloud_id [String]: The short name or ARN of an existing SNS topic
|
|
60
|
+
# @param endpoint [String]: The address, identifier, or ARN of the resource being subscribed
|
|
61
|
+
# @param protocol [String]: The protocol being subscribed
|
|
62
|
+
# @param region [String]: The region of the target SNS topic
|
|
63
|
+
# @param credentials [String]:
|
|
64
|
+
def self.subscribe(cloud_id, endpoint, protocol, region: nil, credentials: nil)
|
|
65
|
+
topic = find(cloud_id: cloud_id, region: region, credentials: credentials).values.first
|
|
66
|
+
if !topic
|
|
67
|
+
raise MuError, "Failed to find SNS Topic #{cloud_id} in #{region}"
|
|
68
|
+
end
|
|
69
|
+
arn = topic["TopicArn"]
|
|
70
|
+
|
|
71
|
+
resp = MU::Cloud::AWS.sns(region: region, credentials: credentials).list_subscriptions_by_topic(topic_arn: arn).subscriptions
|
|
72
|
+
|
|
73
|
+
resp.each { |subscription|
|
|
74
|
+
return subscription if subscription.protocol == protocol and subscription.endpoint == endpoint
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
MU.log "Subscribing #{endpoint} (#{protocol}) to SNS topic #{arn}", MU::NOTICE
|
|
78
|
+
MU::Cloud::AWS.sns(region: region, credentials: credentials).subscribe(topic_arn: arn, protocol: protocol, endpoint: endpoint)
|
|
79
|
+
end
|
|
80
|
+
|
|
50
81
|
# Does this resource type exist as a global (cloud-wide) artifact, or
|
|
51
82
|
# is it localized to a region/zone?
|
|
52
83
|
# @return [Boolean]
|
|
@@ -65,12 +96,12 @@ module MU
|
|
|
65
96
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
66
97
|
# @param region [String]: The cloud provider region
|
|
67
98
|
# @return [void]
|
|
68
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
99
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
69
100
|
MU.log "AWS::Notifier.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
70
101
|
MU.log "Placeholder: AWS Notifier artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
71
102
|
|
|
72
103
|
MU::Cloud::AWS.sns(region: region, credentials: credentials).list_topics.topics.each { |topic|
|
|
73
|
-
if topic.topic_arn.match(
|
|
104
|
+
if topic.topic_arn.match(deploy_id)
|
|
74
105
|
# We don't have a way to tag our SNS topics, so we will delete any topic that has the MU-ID in its ARN.
|
|
75
106
|
# This may fail to find notifier groups in some cases (eg. cache_cluster) so we might want to delete from each API as well.
|
|
76
107
|
MU.log "Deleting SNS topic: #{topic.topic_arn}"
|
|
@@ -91,6 +122,7 @@ module MU
|
|
|
91
122
|
# Return the metadata for this user cofiguration
|
|
92
123
|
# @return [Hash]
|
|
93
124
|
def notify
|
|
125
|
+
return nil if !@cloud_id or !cloud_desc(use_cache: false)
|
|
94
126
|
desc = MU::Cloud::AWS.sns(region: @config["region"], credentials: @config["credentials"]).get_topic_attributes(topic_arn: arn).attributes
|
|
95
127
|
MU.structToHash(desc)
|
|
96
128
|
end
|
|
@@ -101,9 +133,16 @@ module MU
|
|
|
101
133
|
found = {}
|
|
102
134
|
|
|
103
135
|
if args[:cloud_id]
|
|
104
|
-
arn =
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
arn = if args[:cloud_id].match(/^arn:/)
|
|
137
|
+
args[:cloud_id]
|
|
138
|
+
else
|
|
139
|
+
"arn:"+(MU::Cloud::AWS.isGovCloud?(args[:region]) ? "aws-us-gov" : "aws")+":sns:"+args[:region]+":"+MU::Cloud::AWS.credToAcct(args[:credentials])+":"+args[:cloud_id]
|
|
140
|
+
end
|
|
141
|
+
begin
|
|
142
|
+
desc = MU::Cloud::AWS.sns(region: args[:region], credentials: args[:credentials]).get_topic_attributes(topic_arn: arn).attributes
|
|
143
|
+
found[args[:cloud_id]] = desc if desc
|
|
144
|
+
rescue ::Aws::SNS::Errors::NotFound
|
|
145
|
+
end
|
|
107
146
|
else
|
|
108
147
|
next_token = nil
|
|
109
148
|
begin
|
|
@@ -120,6 +159,58 @@ module MU
|
|
|
120
159
|
found
|
|
121
160
|
end
|
|
122
161
|
|
|
162
|
+
# Reverse-map our cloud description into a runnable config hash.
|
|
163
|
+
# We assume that any values we have in +@config+ are placeholders, and
|
|
164
|
+
# calculate our own accordingly based on what's live in the cloud.
|
|
165
|
+
def toKitten(**_args)
|
|
166
|
+
bok = {
|
|
167
|
+
"cloud" => "AWS",
|
|
168
|
+
"credentials" => @config['credentials'],
|
|
169
|
+
"cloud_id" => @cloud_id,
|
|
170
|
+
"region" => @config['region']
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if !cloud_desc
|
|
174
|
+
MU.log "toKitten failed to load a cloud_desc from #{@cloud_id}", MU::ERR, details: @config
|
|
175
|
+
return nil
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
bok['name'] = cloud_desc["DisplayName"].empty? ? @cloud_id : cloud_desc["DisplayName"]
|
|
179
|
+
svcmap = {
|
|
180
|
+
"lambda" => "functions",
|
|
181
|
+
"sqs" => "msg_queues"
|
|
182
|
+
}
|
|
183
|
+
MU::Cloud::AWS.sns(region: @config['region'], credentials: @credentials).list_subscriptions_by_topic(topic_arn: cloud_desc["TopicArn"]).subscriptions.each { |sub|
|
|
184
|
+
bok['subscriptions'] ||= []
|
|
185
|
+
|
|
186
|
+
bok['subscriptions'] << if sub.endpoint.match(/^arn:[^:]+:(sqs|lambda):([^:]+):(\d+):.*?([^:\/]+)$/)
|
|
187
|
+
_wholestring, service, region, account, id = Regexp.last_match.to_a
|
|
188
|
+
{
|
|
189
|
+
"type" => sub.protocol,
|
|
190
|
+
"resource" => MU::Config::Ref.get(
|
|
191
|
+
type: svcmap[service],
|
|
192
|
+
region: region,
|
|
193
|
+
credentials: @credentials,
|
|
194
|
+
id: id,
|
|
195
|
+
cloud: "AWS",
|
|
196
|
+
habitat: MU::Config::Ref.get(
|
|
197
|
+
id: account,
|
|
198
|
+
cloud: "AWS",
|
|
199
|
+
credentials: @credentials
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
else
|
|
204
|
+
{
|
|
205
|
+
"type" => sub.protocol,
|
|
206
|
+
"endpoint" => sub.endpoint
|
|
207
|
+
}
|
|
208
|
+
end
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
bok
|
|
212
|
+
end
|
|
213
|
+
|
|
123
214
|
# Cloud-specific configuration properties.
|
|
124
215
|
# @param _config [MU::Config]: The calling MU::Config object
|
|
125
216
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
@@ -130,11 +221,10 @@ module MU
|
|
|
130
221
|
"type" => "array",
|
|
131
222
|
"items" => {
|
|
132
223
|
"type" => "object",
|
|
133
|
-
"required" => ["endpoint"],
|
|
134
224
|
"properties" => {
|
|
135
225
|
"type" => {
|
|
136
226
|
"type" => "string",
|
|
137
|
-
"description" => "",
|
|
227
|
+
"description" => "Type of endpoint or resource which should receive notifications. If not specified, will attempt to auto-detect.",
|
|
138
228
|
"enum" => ["http", "https", "email", "email-json", "sms", "sqs", "application", "lambda"]
|
|
139
229
|
}
|
|
140
230
|
}
|
|
@@ -148,26 +238,42 @@ module MU
|
|
|
148
238
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::notifier}, bare and unvalidated.
|
|
149
239
|
|
|
150
240
|
# @param notifier [Hash]: The resource to process and validate
|
|
151
|
-
# @param
|
|
241
|
+
# @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
152
242
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
153
|
-
def self.validateConfig(notifier,
|
|
243
|
+
def self.validateConfig(notifier, configurator)
|
|
154
244
|
ok = true
|
|
155
245
|
|
|
156
246
|
if notifier['subscriptions']
|
|
157
247
|
notifier['subscriptions'].each { |sub|
|
|
248
|
+
if sub['resource'] and configurator.haveLitterMate?(sub['resource']['name'], sub['resource']['type'])
|
|
249
|
+
sub['resource']['cloud'] = "AWS"
|
|
250
|
+
MU::Config.addDependency(notifier, sub['resource']['name'], sub['resource']['type'])
|
|
251
|
+
end
|
|
158
252
|
if !sub["type"]
|
|
159
|
-
if sub[
|
|
160
|
-
sub[
|
|
161
|
-
|
|
162
|
-
sub[
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
elsif sub[
|
|
166
|
-
sub["
|
|
167
|
-
|
|
168
|
-
sub["
|
|
169
|
-
|
|
170
|
-
|
|
253
|
+
sub['type'] = if sub['resource']
|
|
254
|
+
if sub['resource']['type'] == "functions"
|
|
255
|
+
"lambda"
|
|
256
|
+
elsif sub['resource']['type'] == "msg_queues"
|
|
257
|
+
"sqs"
|
|
258
|
+
end
|
|
259
|
+
elsif sub['endpoint']
|
|
260
|
+
if sub["endpoint"].match(/^http:/i)
|
|
261
|
+
"http"
|
|
262
|
+
elsif sub["endpoint"].match(/^https:/i)
|
|
263
|
+
"https"
|
|
264
|
+
elsif sub["endpoint"].match(/:sqs:/i)
|
|
265
|
+
"sqs"
|
|
266
|
+
elsif sub["endpoint"].match(/:lambda:/i)
|
|
267
|
+
"lambda"
|
|
268
|
+
elsif sub["endpoint"].match(/^\+?[\d\-]+$/)
|
|
269
|
+
"sms"
|
|
270
|
+
elsif sub["endpoint"].match(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
|
|
271
|
+
"email"
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
if !sub['type']
|
|
276
|
+
MU.log "Notifier #{notifier['name']} subscription did not specify a type, and I'm unable to guess one", MU::ERR, details: sub
|
|
171
277
|
ok = false
|
|
172
278
|
end
|
|
173
279
|
end
|
|
@@ -178,40 +284,6 @@ module MU
|
|
|
178
284
|
end
|
|
179
285
|
|
|
180
286
|
|
|
181
|
-
# Subscribe to a notifier group. This can either be an email address, SQS queue, application endpoint, etc...
|
|
182
|
-
# Will create the subscription only if it doesn't already exist.
|
|
183
|
-
# @param arn [String]: The cloud provider's identifier of the notifier group.
|
|
184
|
-
# @param protocol [String]: The type of the subscription (eg. email,https, etc..).
|
|
185
|
-
# @param endpoint [String]: The endpoint of the subscription. This will depend on the 'protocol' (as an example if protocol is email, endpoint will be the email address) ..
|
|
186
|
-
# @param region [String]: The cloud provider region.
|
|
187
|
-
def self.subscribe(arn: nil, protocol: nil, endpoint: nil, region: MU.curRegion, credentials: nil)
|
|
188
|
-
retries = 0
|
|
189
|
-
begin
|
|
190
|
-
resp = MU::Cloud::AWS.sns(region: region, credentials: credentials).list_subscriptions_by_topic(topic_arn: arn).subscriptions
|
|
191
|
-
rescue Aws::SNS::Errors::NotFound
|
|
192
|
-
if retries < 5
|
|
193
|
-
MU.log "Couldn't find topic #{arn}, retrying several times in case of a lagging resource"
|
|
194
|
-
retries += 1
|
|
195
|
-
sleep 30
|
|
196
|
-
retry
|
|
197
|
-
else
|
|
198
|
-
raise MuError, "Couldn't find topic #{arn}, giving up"
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
already_subscribed = false
|
|
203
|
-
if resp && !resp.empty?
|
|
204
|
-
resp.each { |subscription|
|
|
205
|
-
already_subscribed = true if subscription.protocol == protocol && subscription.endpoint == endpoint
|
|
206
|
-
}
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
unless already_subscribed
|
|
210
|
-
MU::Cloud::AWS.sns(region: region, credentials: credentials).subscribe(topic_arn: arn, protocol: protocol, endpoint: endpoint)
|
|
211
|
-
MU.log "Subscribed #{endpoint} to SNS topic #{arn}"
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
287
|
# Test if a notifier group exists
|
|
216
288
|
# Create a new notifier group. Will check if the group exists before creating it.
|
|
217
289
|
# @param topic_name [String]: The cloud provider's name for the notifier group.
|
|
@@ -30,7 +30,7 @@ module MU
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
@mu_name ||= @deploy.getResourceName(@config["name"])
|
|
33
|
+
@mu_name ||= @deploy.getResourceName(@config["name"], max_length: 64)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Called automatically by {MU::Deploy#createResources}
|
|
@@ -43,7 +43,7 @@ module MU
|
|
|
43
43
|
|
|
44
44
|
policy_name = @mu_name+"-"+policy.keys.first.upcase
|
|
45
45
|
MU.log "Creating IAM policy #{policy_name}"
|
|
46
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
46
|
+
MU::Cloud::AWS.iam(credentials: @credentials).create_policy(
|
|
47
47
|
policy_name: policy_name,
|
|
48
48
|
path: "/"+@deploy.deploy_id+"/",
|
|
49
49
|
policy_document: JSON.generate(policy.values.first),
|
|
@@ -53,16 +53,18 @@ module MU
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
if !@config['bare_policies']
|
|
56
|
-
MU.log "Creating IAM role #{@mu_name}"
|
|
57
56
|
@cloud_id = @mu_name
|
|
58
57
|
path = @config['strip_path'] ? nil : "/"+@deploy.deploy_id+"/"
|
|
59
|
-
|
|
60
|
-
path
|
|
61
|
-
role_name
|
|
62
|
-
description
|
|
63
|
-
assume_role_policy_document
|
|
64
|
-
tags
|
|
65
|
-
|
|
58
|
+
params = {
|
|
59
|
+
:path => path,
|
|
60
|
+
:role_name => @mu_name,
|
|
61
|
+
:description => "Generated by Mu",
|
|
62
|
+
:assume_role_policy_document => gen_assume_role_policy_doc,
|
|
63
|
+
:tags => get_tag_params
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
MU.log "Creating IAM role #{@mu_name} (#{@credentials})", details: params
|
|
67
|
+
MU::Cloud::AWS.iam(credentials: @credentials).create_role(params)
|
|
66
68
|
end
|
|
67
69
|
end
|
|
68
70
|
|
|
@@ -75,7 +77,7 @@ module MU
|
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
if !@config['bare_policies']
|
|
78
|
-
resp = MU::Cloud::AWS.iam(credentials: @
|
|
80
|
+
resp = MU::Cloud::AWS.iam(credentials: @credentials).get_role(
|
|
79
81
|
role_name: @mu_name
|
|
80
82
|
).role
|
|
81
83
|
ext_tags = resp.tags.map { |t| t.to_h }
|
|
@@ -84,7 +86,7 @@ module MU
|
|
|
84
86
|
|
|
85
87
|
if tag_param.size > 0
|
|
86
88
|
MU.log "Updating tags on IAM role #{@mu_name}", MU::NOTICE, details: tag_param
|
|
87
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
89
|
+
MU::Cloud::AWS.iam(credentials: @credentials).tag_role(role_name: @mu_name, tags: tag_param)
|
|
88
90
|
end
|
|
89
91
|
end
|
|
90
92
|
|
|
@@ -92,13 +94,14 @@ module MU
|
|
|
92
94
|
configured_policies = []
|
|
93
95
|
|
|
94
96
|
if @config['raw_policies']
|
|
97
|
+
MU.log "Attaching #{@config['raw_policies'].size.to_s} raw #{@config['raw_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
|
|
95
98
|
configured_policies = @config['raw_policies'].map { |p|
|
|
96
99
|
@mu_name+"-"+p.keys.first.upcase
|
|
97
100
|
}
|
|
98
101
|
end
|
|
99
102
|
|
|
100
103
|
if @config['attachable_policies']
|
|
101
|
-
MU.log "Attaching #{@config['attachable_policies'].size.to_s} #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
|
|
104
|
+
MU.log "Attaching #{@config['attachable_policies'].size.to_s} external #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
|
|
102
105
|
configured_policies.concat(@config['attachable_policies'].map { |p|
|
|
103
106
|
id = if p.is_a?(MU::Config::Ref)
|
|
104
107
|
p.cloud_id
|
|
@@ -109,18 +112,17 @@ module MU
|
|
|
109
112
|
end
|
|
110
113
|
id.gsub(/.*?\/([^:\/]+)$/, '\1')
|
|
111
114
|
})
|
|
112
|
-
configured_policies.each { |pol|
|
|
113
|
-
}
|
|
114
115
|
end
|
|
115
116
|
|
|
117
|
+
# Purge anything that doesn't belong
|
|
116
118
|
if !@config['bare_policies']
|
|
117
|
-
attached_policies = MU::Cloud::AWS.iam(credentials: @
|
|
119
|
+
attached_policies = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
|
|
118
120
|
role_name: @mu_name
|
|
119
121
|
).attached_policies
|
|
120
122
|
attached_policies.each { |a|
|
|
121
123
|
if !configured_policies.include?(a.policy_name)
|
|
122
|
-
MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE
|
|
123
|
-
MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @
|
|
124
|
+
MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE, details: configured_policies
|
|
125
|
+
MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @credentials)
|
|
124
126
|
end
|
|
125
127
|
}
|
|
126
128
|
end
|
|
@@ -153,8 +155,8 @@ module MU
|
|
|
153
155
|
policy.values.each { |p|
|
|
154
156
|
p["Version"] ||= "2012-10-17"
|
|
155
157
|
}
|
|
156
|
-
policy_name = basename+"-"+policy.keys.first.upcase
|
|
157
158
|
|
|
159
|
+
policy_name = basename+"-"+policy.keys.first.upcase
|
|
158
160
|
arn = "arn:"+(MU::Cloud::AWS.isGovCloud? ? "aws-us-gov" : "aws")+":iam::"+MU::Cloud::AWS.credToAcct(credentials)+":policy#{path}/#{policy_name}"
|
|
159
161
|
resp = begin
|
|
160
162
|
desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
|
|
@@ -184,12 +186,17 @@ module MU
|
|
|
184
186
|
|
|
185
187
|
rescue Aws::IAM::Errors::NoSuchEntity
|
|
186
188
|
MU.log "Creating IAM policy #{policy_name}", details: policy.values.first
|
|
187
|
-
MU::Cloud::AWS.iam(credentials: credentials).create_policy(
|
|
189
|
+
desc = MU::Cloud::AWS.iam(credentials: credentials).create_policy(
|
|
188
190
|
policy_name: policy_name,
|
|
189
191
|
path: path+"/",
|
|
190
192
|
policy_document: JSON.generate(policy.values.first),
|
|
191
193
|
description: "Raw policy from #{basename}"
|
|
192
194
|
)
|
|
195
|
+
MU.retrier([Aws::IAM::Errors::NoSuchEntity], loop_if: Proc.new { desc.nil? }) {
|
|
196
|
+
desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
|
|
197
|
+
pp desc
|
|
198
|
+
}
|
|
199
|
+
desc
|
|
193
200
|
end
|
|
194
201
|
arns << resp.policy.arn
|
|
195
202
|
}
|
|
@@ -216,7 +223,22 @@ module MU
|
|
|
216
223
|
# populated with one or both depending on what this resource has
|
|
217
224
|
# defined.
|
|
218
225
|
def cloud_desc(use_cache: true)
|
|
219
|
-
|
|
226
|
+
|
|
227
|
+
# we might inherit a naive cached description from the base cloud
|
|
228
|
+
# layer; rearrange it to our tastes
|
|
229
|
+
if @cloud_desc_cache.is_a?(::Aws::IAM::Types::Role)
|
|
230
|
+
new_desc = {
|
|
231
|
+
"role" => @cloud_desc_cache
|
|
232
|
+
}
|
|
233
|
+
@cloud_desc_cache = new_desc
|
|
234
|
+
elsif @cloud_desc_cache.is_a?(::Aws::IAM::Types::Policy)
|
|
235
|
+
new_desc = {
|
|
236
|
+
"policies" => [@cloud_desc_cache]
|
|
237
|
+
}
|
|
238
|
+
@cloud_desc_cache = new_desc
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
return @cloud_desc_cache if @cloud_desc_cache and !@cloud_desc_cache.empty? and use_cache
|
|
220
242
|
|
|
221
243
|
@cloud_desc_cache = {}
|
|
222
244
|
if @config['bare_policies']
|
|
@@ -301,7 +323,7 @@ end
|
|
|
301
323
|
my_policies.each { |p|
|
|
302
324
|
if p.policy_name == policy
|
|
303
325
|
seen_policy = true
|
|
304
|
-
old = MU::Cloud::AWS.iam(credentials: @
|
|
326
|
+
old = MU::Cloud::AWS.iam(credentials: @credentials).get_policy_version(
|
|
305
327
|
policy_arn: p.arn,
|
|
306
328
|
version_id: p.default_version_id
|
|
307
329
|
).policy_version
|
|
@@ -419,14 +441,14 @@ end
|
|
|
419
441
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
420
442
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
421
443
|
# @return [void]
|
|
422
|
-
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
444
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
|
|
423
445
|
|
|
424
446
|
resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
|
|
425
|
-
path_prefix: "/"+
|
|
447
|
+
path_prefix: "/"+deploy_id+"/"
|
|
426
448
|
)
|
|
427
449
|
if resp and resp.policies
|
|
428
450
|
resp.policies.each { |policy|
|
|
429
|
-
MU.log "Deleting IAM policy /#{
|
|
451
|
+
MU.log "Deleting IAM policy /#{deploy_id}/#{policy.policy_name}"
|
|
430
452
|
if !noop
|
|
431
453
|
purgePolicy(policy.arn, credentials)
|
|
432
454
|
end
|
|
@@ -437,19 +459,23 @@ end
|
|
|
437
459
|
roles = MU::Cloud::AWS::Role.find(credentials: credentials).values
|
|
438
460
|
roles.each { |r|
|
|
439
461
|
next if !r.respond_to?(:role_name)
|
|
440
|
-
if r.path.match(/^\/#{Regexp.quote(
|
|
462
|
+
if r.path.match(/^\/#{Regexp.quote(deploy_id)}/)
|
|
441
463
|
deleteme << r
|
|
442
464
|
next
|
|
443
465
|
end
|
|
444
466
|
# For some dumb reason, the list output that .find gets doesn't
|
|
445
467
|
# include the tags, so we need to fetch each role individually to
|
|
446
468
|
# check tags. Hardly seems efficient.
|
|
447
|
-
desc =
|
|
469
|
+
desc = begin
|
|
470
|
+
MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
|
|
471
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
472
|
+
next
|
|
473
|
+
end
|
|
448
474
|
if desc.role and desc.role.tags and desc.role.tags
|
|
449
475
|
master_match = false
|
|
450
476
|
deploy_match = false
|
|
451
477
|
desc.role.tags.each { |t|
|
|
452
|
-
if t.key == "MU-ID" and t.value ==
|
|
478
|
+
if t.key == "MU-ID" and t.value == deploy_id
|
|
453
479
|
deploy_match = true
|
|
454
480
|
elsif t.key == "MU-MASTER-IP" and t.value == MU.mu_public_ip
|
|
455
481
|
master_match = true
|
|
@@ -516,7 +542,7 @@ end
|
|
|
516
542
|
|
|
517
543
|
begin
|
|
518
544
|
# managed policies get fetched by ARN, roles by plain name. Ok!
|
|
519
|
-
if args[:cloud_id].match(/^arn
|
|
545
|
+
if args[:cloud_id].match(/^arn:.*?:policy\//)
|
|
520
546
|
resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_policy(
|
|
521
547
|
policy_arn: args[:cloud_id]
|
|
522
548
|
)
|
|
@@ -525,39 +551,26 @@ end
|
|
|
525
551
|
end
|
|
526
552
|
else
|
|
527
553
|
resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_role(
|
|
528
|
-
role_name: args[:cloud_id]
|
|
554
|
+
role_name: args[:cloud_id].sub(/^arn:.*?\/([^:\/]+)$/, '\1') # XXX if it's an ARN, actually parse it and look in the correct account when applicable
|
|
529
555
|
)
|
|
556
|
+
|
|
530
557
|
if resp and resp.role
|
|
531
|
-
found[
|
|
558
|
+
found[resp.role.role_name] = resp.role
|
|
532
559
|
end
|
|
533
560
|
end
|
|
534
561
|
rescue ::Aws::IAM::Errors::NoSuchEntity
|
|
535
562
|
end
|
|
536
563
|
|
|
537
564
|
else
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
)
|
|
543
|
-
break if !resp or !resp.roles
|
|
544
|
-
resp.roles.each { |role|
|
|
545
|
-
found[role.role_name] = role
|
|
546
|
-
}
|
|
547
|
-
marker = resp.marker
|
|
548
|
-
end while marker
|
|
565
|
+
resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_roles
|
|
566
|
+
resp.roles.each { |role|
|
|
567
|
+
found[role.role_name] = role
|
|
568
|
+
}
|
|
549
569
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
)
|
|
555
|
-
break if !resp or !resp.policies
|
|
556
|
-
resp.policies.each { |pol|
|
|
557
|
-
found[pol.arn] = pol
|
|
558
|
-
}
|
|
559
|
-
marker = resp.marker
|
|
560
|
-
end while marker
|
|
570
|
+
resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_policies(scope: "Local")
|
|
571
|
+
resp.policies.each { |pol|
|
|
572
|
+
found[pol.arn] = pol
|
|
573
|
+
}
|
|
561
574
|
end
|
|
562
575
|
|
|
563
576
|
found
|
|
@@ -569,7 +582,7 @@ end
|
|
|
569
582
|
def toKitten(**_args)
|
|
570
583
|
bok = {
|
|
571
584
|
"cloud" => "AWS",
|
|
572
|
-
"credentials" => @
|
|
585
|
+
"credentials" => @credentials,
|
|
573
586
|
"cloud_id" => @cloud_id
|
|
574
587
|
}
|
|
575
588
|
|
|
@@ -615,7 +628,6 @@ end
|
|
|
615
628
|
)
|
|
616
629
|
JSON.parse(URI.decode(version.policy_version.document))
|
|
617
630
|
end
|
|
618
|
-
|
|
619
631
|
bok["policies"] = MU::Cloud::AWS::Role.doc2MuPolicies(pol.policy_name, doc, bok["policies"])
|
|
620
632
|
end
|
|
621
633
|
}
|
|
@@ -695,6 +707,7 @@ end
|
|
|
695
707
|
end
|
|
696
708
|
|
|
697
709
|
bok["attachable_policies"].uniq! if bok["attachable_policies"]
|
|
710
|
+
bok["name"].gsub!(/[^a-zA-Z0-9_\-]/, "_")
|
|
698
711
|
|
|
699
712
|
bok
|
|
700
713
|
end
|
|
@@ -707,6 +720,10 @@ end
|
|
|
707
720
|
def self.doc2MuPolicies(basename, doc, policies = [])
|
|
708
721
|
policies ||= []
|
|
709
722
|
|
|
723
|
+
if !doc["Statement"].is_a?(Array)
|
|
724
|
+
doc["Statement"] = [doc["Statement"]]
|
|
725
|
+
end
|
|
726
|
+
|
|
710
727
|
doc["Statement"].each { |s|
|
|
711
728
|
if !s["Action"]
|
|
712
729
|
MU.log "Statement in policy document for #{basename} didn't have an Action field", MU::WARN, details: doc
|
|
@@ -758,12 +775,12 @@ end
|
|
|
758
775
|
def bindTo(entitytype, entityname)
|
|
759
776
|
if entitytype == "instance_profile"
|
|
760
777
|
begin
|
|
761
|
-
resp = MU::Cloud::AWS.iam(credentials: @
|
|
778
|
+
resp = MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
|
|
762
779
|
instance_profile_name: entityname
|
|
763
780
|
).instance_profile
|
|
764
781
|
|
|
765
782
|
if !resp.roles.map { |r| r.role_name}.include?(@mu_name)
|
|
766
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
783
|
+
MU::Cloud::AWS.iam(credentials: @credentials).add_role_to_instance_profile(
|
|
767
784
|
instance_profile_name: entityname,
|
|
768
785
|
role_name: @mu_name
|
|
769
786
|
)
|
|
@@ -773,7 +790,7 @@ end
|
|
|
773
790
|
raise e
|
|
774
791
|
end
|
|
775
792
|
elsif ["user", "group", "role"].include?(entitytype)
|
|
776
|
-
mypolicies = MU::Cloud::AWS.iam(credentials: @
|
|
793
|
+
mypolicies = MU::Cloud::AWS.iam(credentials: @credentials).list_policies(
|
|
777
794
|
path_prefix: "/"+@deploy.deploy_id+"/"
|
|
778
795
|
).policies
|
|
779
796
|
mypolicies.reject! { |p|
|
|
@@ -791,7 +808,7 @@ end
|
|
|
791
808
|
|
|
792
809
|
subpaths = ["service-role", "aws-service-role", "job-function"]
|
|
793
810
|
begin
|
|
794
|
-
mypolicies << MU::Cloud::AWS.iam(credentials: @
|
|
811
|
+
mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
|
|
795
812
|
policy_arn: p_arn
|
|
796
813
|
).policy
|
|
797
814
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
|
@@ -804,39 +821,52 @@ end
|
|
|
804
821
|
}
|
|
805
822
|
end
|
|
806
823
|
|
|
824
|
+
if @config['raw_policies']
|
|
825
|
+
raw_arns = MU::Cloud::AWS::Role.manageRawPolicies(
|
|
826
|
+
@config['raw_policies'],
|
|
827
|
+
basename: @deploy.getResourceName(@config['name']),
|
|
828
|
+
credentials: @credentials
|
|
829
|
+
)
|
|
830
|
+
raw_arns.each { |p_arn|
|
|
831
|
+
mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
|
|
832
|
+
policy_arn: p_arn
|
|
833
|
+
).policy
|
|
834
|
+
}
|
|
835
|
+
end
|
|
836
|
+
|
|
807
837
|
mypolicies.each { |p|
|
|
808
838
|
if entitytype == "user"
|
|
809
|
-
resp = MU::Cloud::AWS.iam(credentials: @
|
|
839
|
+
resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_user_policies(
|
|
810
840
|
path_prefix: "/"+@deploy.deploy_id+"/",
|
|
811
841
|
user_name: entityname
|
|
812
842
|
)
|
|
813
843
|
if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
|
|
814
844
|
MU.log "Attaching IAM policy #{p.policy_name} to user #{entityname}", MU::NOTICE
|
|
815
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
845
|
+
MU::Cloud::AWS.iam(credentials: @credentials).attach_user_policy(
|
|
816
846
|
policy_arn: p.arn,
|
|
817
847
|
user_name: entityname
|
|
818
848
|
)
|
|
819
849
|
end
|
|
820
850
|
elsif entitytype == "group"
|
|
821
|
-
resp = MU::Cloud::AWS.iam(credentials: @
|
|
851
|
+
resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_group_policies(
|
|
822
852
|
path_prefix: "/"+@deploy.deploy_id+"/",
|
|
823
853
|
group_name: entityname
|
|
824
854
|
)
|
|
825
855
|
if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
|
|
826
856
|
MU.log "Attaching policy #{p.policy_name} to group #{entityname}", MU::NOTICE
|
|
827
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
857
|
+
MU::Cloud::AWS.iam(credentials: @credentials).attach_group_policy(
|
|
828
858
|
policy_arn: p.arn,
|
|
829
859
|
group_name: entityname
|
|
830
860
|
)
|
|
831
861
|
end
|
|
832
862
|
elsif entitytype == "role"
|
|
833
|
-
resp = MU::Cloud::AWS.iam(credentials: @
|
|
863
|
+
resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
|
|
834
864
|
role_name: entityname
|
|
835
865
|
)
|
|
836
866
|
|
|
837
867
|
if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
|
|
838
868
|
MU.log "Attaching policy #{p.policy_name} to role #{entityname}", MU::NOTICE
|
|
839
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
869
|
+
MU::Cloud::AWS.iam(credentials: @credentials).attach_role_policy(
|
|
840
870
|
policy_arn: p.arn,
|
|
841
871
|
role_name: entityname
|
|
842
872
|
)
|
|
@@ -857,19 +887,19 @@ end
|
|
|
857
887
|
end
|
|
858
888
|
|
|
859
889
|
resp = begin
|
|
860
|
-
MU.log "Creating instance profile #{@mu_name} #{@
|
|
861
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
890
|
+
MU.log "Creating instance profile #{@mu_name} #{@credentials}"
|
|
891
|
+
MU::Cloud::AWS.iam(credentials: @credentials).create_instance_profile(
|
|
862
892
|
instance_profile_name: @mu_name
|
|
863
893
|
)
|
|
864
894
|
rescue Aws::IAM::Errors::EntityAlreadyExists
|
|
865
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
895
|
+
MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
|
|
866
896
|
instance_profile_name: @mu_name
|
|
867
897
|
)
|
|
868
898
|
end
|
|
869
899
|
|
|
870
900
|
# make sure it's really there before moving on
|
|
871
901
|
begin
|
|
872
|
-
MU::Cloud::AWS.iam(credentials: @
|
|
902
|
+
MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(instance_profile_name: @mu_name)
|
|
873
903
|
rescue Aws::IAM::Errors::NoSuchEntity => e
|
|
874
904
|
MU.log e.inspect, MU::WARN
|
|
875
905
|
sleep 10
|
|
@@ -925,7 +955,7 @@ end
|
|
|
925
955
|
toplevel_required = []
|
|
926
956
|
aws_resource_types = MU::Cloud.resource_types.keys.reject { |t|
|
|
927
957
|
begin
|
|
928
|
-
MU::Cloud.
|
|
958
|
+
MU::Cloud.resourceClass("AWS", t)
|
|
929
959
|
false
|
|
930
960
|
rescue MuCloudResourceNotImplemented
|
|
931
961
|
true
|
|
@@ -1087,11 +1117,7 @@ end
|
|
|
1087
1117
|
role['policies'].each { |policy|
|
|
1088
1118
|
policy['targets'].each { |target|
|
|
1089
1119
|
if target['type']
|
|
1090
|
-
role['
|
|
1091
|
-
role['dependencies'] << {
|
|
1092
|
-
"name" => target['identifier'],
|
|
1093
|
-
"type" => target['type']
|
|
1094
|
-
}
|
|
1120
|
+
MU::Config.addDependency(role, target['identifier'], target['type'], no_create_wait: true)
|
|
1095
1121
|
end
|
|
1096
1122
|
}
|
|
1097
1123
|
}
|
|
@@ -1107,13 +1133,14 @@ end
|
|
|
1107
1133
|
# @param policies [Array<Hash>]: One or more policy chunks
|
|
1108
1134
|
# @param deploy_obj [MU::MommaCat]: Deployment object to use when looking up sibling Mu resources
|
|
1109
1135
|
# @return [Array<Hash>]
|
|
1110
|
-
def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false)
|
|
1136
|
+
def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false, version: "2012-10-17", doc_id: nil)
|
|
1111
1137
|
if policies
|
|
1112
1138
|
name = nil
|
|
1113
1139
|
doc = {
|
|
1114
|
-
"Version" =>
|
|
1140
|
+
"Version" => version,
|
|
1115
1141
|
"Statement" => []
|
|
1116
1142
|
}
|
|
1143
|
+
doc["Id"] = doc_id if doc_id
|
|
1117
1144
|
policies.each { |policy|
|
|
1118
1145
|
policy["flag"] ||= "Allow"
|
|
1119
1146
|
statement = {
|
|
@@ -1154,7 +1181,14 @@ end
|
|
|
1154
1181
|
raise MuError, "Couldn't find a #{grantee["type"]} named #{grantee["identifier"]} when generating IAM policy"
|
|
1155
1182
|
end
|
|
1156
1183
|
else
|
|
1157
|
-
bucket_prefix = grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/)
|
|
1184
|
+
bucket_prefix = if grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/)
|
|
1185
|
+
"Service"
|
|
1186
|
+
elsif grantee["identifier"] =~ /^[a-f0-9]+$/
|
|
1187
|
+
"CanonicalUser"
|
|
1188
|
+
else
|
|
1189
|
+
"AWS"
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1158
1192
|
if bucket_style
|
|
1159
1193
|
statement["Principal"] << { bucket_prefix => grantee["identifier"] }
|
|
1160
1194
|
else
|