miam 0.1.0.beta

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,248 @@
1
+ class Miam::Driver
2
+ include Miam::Logger::Helper
3
+
4
+ MAX_POLICY_SIZE = 2048
5
+
6
+ def initialize(iam, options = {})
7
+ @iam = iam
8
+ @options = options
9
+ end
10
+
11
+ def create_user(user_name, attrs)
12
+ log(:info, "Create User `#{user_name}`", :color => :cyan)
13
+
14
+ unless_dry_run do
15
+ params = {:user_name => user_name}
16
+ params[:path] = attrs[:path] if attrs[:path]
17
+ @iam.create_user(params)
18
+ end
19
+
20
+ new_user_attrs = {:groups => [], :policies => {}}
21
+ new_user_attrs[:path] = attrs[:path] if attrs[:path]
22
+ new_user_attrs
23
+ end
24
+
25
+ def create_access_key(user_name)
26
+ log(:info, "Create access key for User `#{user_name}`", :color => :cyan)
27
+ access_key = nil
28
+
29
+ unless_dry_run do
30
+ resp = @iam.create_access_key(:user_name => user_name)
31
+
32
+ access_key = {
33
+ :access_key_id => resp.access_key.access_key_id,
34
+ :secret_access_key => resp.access_key.secret_access_key,
35
+ }
36
+ end
37
+
38
+ access_key
39
+ end
40
+
41
+ def delete_user(user_name, attrs)
42
+ log(:info, "Delete User `#{user_name}`", :color => :red)
43
+
44
+ unless_dry_run do
45
+ if attrs[:login_profile]
46
+ @iam.delete_login_profile(:user_name => user_name)
47
+ end
48
+
49
+ attrs[:policies].keys.each do |policy_name|
50
+ @iam.delete_user_policy(:user_name => user_name, :policy_name => policy_name)
51
+ end
52
+
53
+ attrs[:groups].each do |group_name|
54
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
55
+ end
56
+
57
+ list_access_key_ids(user_name).each do |access_key_id|
58
+ @iam.delete_access_key(:user_name => user_name, :access_key_id => access_key_id)
59
+ end
60
+
61
+ list_signing_certificate_ids(user_name).each do |certificate_id|
62
+ @iam.delete_signing_certificate(:user_name => user_name, :certificate_id => certificate_id)
63
+ end
64
+
65
+ @iam.delete_user(:user_name => user_name)
66
+ end
67
+ end
68
+
69
+ def create_login_profile(user_name, attrs)
70
+ log_attrs = attrs.dup
71
+ log_attrs.delete(:password)
72
+
73
+ log(:info, "Update User `#{user_name}`", :color => :green)
74
+ log(:info, " create login profile: #{log_attrs.inspect}", :color => :green)
75
+
76
+ unless_dry_run do
77
+ @iam.create_login_profile(attrs.merge(:user_name => user_name))
78
+ end
79
+ end
80
+
81
+ def delete_login_profile(user_name)
82
+ log(:info, "Update User `#{user_name}`", :color => :green)
83
+ log(:info, " delete login profile", :color => :green)
84
+
85
+ unless_dry_run do
86
+ @iam.delete_login_profile(:user_name => user_name)
87
+ end
88
+ end
89
+
90
+ def update_login_profile(user_name, attrs)
91
+ log_attrs = attrs.dup
92
+ log_attrs.delete(:password)
93
+
94
+ log(:info, "Update User `#{user_name}`", :color => :green)
95
+ log(:info, " update login profile: #{log_attrs.inspect}", :color => :green)
96
+
97
+ unless_dry_run do
98
+ @iam.update_login_profile(attrs.merge(:user_name => user_name))
99
+ end
100
+ end
101
+
102
+ def add_user_to_groups(user_name, group_names)
103
+ log(:info, "Update User `#{user_name}`", :color => :green)
104
+ log(:info, " add groups=#{group_names.join(',')}", :color => :green)
105
+
106
+ unless_dry_run do
107
+ group_names.each do |group_name|
108
+ @iam.add_user_to_group(:group_name => group_name, :user_name => user_name)
109
+ end
110
+ end
111
+ end
112
+
113
+ def remove_user_from_groups(user_name, group_names)
114
+ log(:info, "Update User `#{user_name}`", :color => :green)
115
+ log(:info, " remove groups=#{group_names.join(',')}", :color => :green)
116
+
117
+ unless_dry_run do
118
+ group_names.each do |group_name|
119
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
120
+ end
121
+ end
122
+ end
123
+
124
+ def create_group(group_name, attrs)
125
+ log(:info, "Create Group `#{group_name}`", :color => :cyan)
126
+
127
+ unless_dry_run do
128
+ params = {:group_name => group_name}
129
+ params[:path] = attrs[:path] if attrs[:path]
130
+ @iam.create_group(params)
131
+ end
132
+
133
+ new_group_attrs = {:policies => {}}
134
+ new_group_attrs[:path] = attrs[:path] if attrs[:path]
135
+ new_group_attrs
136
+ end
137
+
138
+ def delete_group(group_name, attrs, users_in_group)
139
+ log(:info, "Delete Group `#{group_name}`", :color => :red)
140
+
141
+ unless_dry_run do
142
+ attrs[:policies].keys.each do |policy_name|
143
+ @iam.delete_group_policy(:group_name => group_name, :policy_name => policy_name)
144
+ end
145
+
146
+ users_in_group.each do |user_name|
147
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
148
+ end
149
+
150
+ @iam.delete_group(:group_name => group_name)
151
+ end
152
+ end
153
+
154
+ def update_name(type, user_or_group_name, new_name)
155
+ log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
156
+ log(:info, " set name=#{new_name}", :color => :green)
157
+ update_user_or_group(type, user_or_group_name, "new_#{type}_name".to_sym => new_name)
158
+ end
159
+
160
+ def update_path(type, user_or_group_name, new_path)
161
+ log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
162
+ log(:info, " set path=#{new_path}", :color => :green)
163
+ update_user_or_group(type, user_or_group_name, :new_path => new_path)
164
+ end
165
+
166
+ def update_user_or_group(type, user_or_group_name, params)
167
+ unless_dry_run do
168
+ params["#{type}_name".to_sym] = user_or_group_name
169
+ @iam.send("update_#{type}", params)
170
+ end
171
+ end
172
+
173
+ def create_policy(type, user_or_group_name, policy_name, policy_document)
174
+ log(:info, "Create #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :cyan)
175
+ log(:info, " #{policy_document.pretty_inspect.gsub("\n", "\n ").strip}", :color => :cyan)
176
+ put_policy(type, user_or_group_name, policy_name, policy_document)
177
+ end
178
+
179
+ def update_policy(type, user_or_group_name, policy_name, policy_document)
180
+ log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :green)
181
+ log(:info, " #{policy_document.pretty_inspect.gsub("\n", "\n ").strip}", :color => :green)
182
+ put_policy(type, user_or_group_name, policy_name, policy_document)
183
+ end
184
+
185
+ def delete_policy(type, user_or_group_name, policy_name)
186
+ logmsg = "Delete #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`"
187
+ log(:info, logmsg, :color => :red)
188
+
189
+ unless_dry_run do
190
+ params = {:policy_name => policy_name}
191
+ params["#{type}_name".to_sym] = user_or_group_name
192
+ @iam.send("delete_#{type}_policy", params)
193
+ end
194
+ end
195
+
196
+ def put_policy(type, user_or_group_name, policy_name, policy_document)
197
+ unless_dry_run do
198
+ params = {
199
+ :policy_name => policy_name,
200
+ :policy_document => encode_document(policy_document),
201
+ }
202
+
203
+ params["#{type}_name".to_sym] = user_or_group_name
204
+ @iam.send("put_#{type}_policy", params)
205
+ end
206
+ end
207
+
208
+ def list_access_key_ids(user_name)
209
+ @iam.list_access_keys(:user_name => user_name).map {|resp|
210
+ resp.access_key_metadata.map do |metadata|
211
+ metadata.access_key_id
212
+ end
213
+ }.flatten
214
+ end
215
+
216
+ def list_signing_certificate_ids(user_name)
217
+ @iam.list_signing_certificates(:user_name => user_name).map {|resp|
218
+ resp.certificates.map do |cert|
219
+ cert.certificate_id
220
+ end
221
+ }.flatten
222
+ end
223
+
224
+ private
225
+
226
+ def encode_document(policy_document)
227
+ if @options[:disable_form_json]
228
+ JSON.dump(policy_document)
229
+ else
230
+ encoded = JSON.pretty_generate(policy_document)
231
+
232
+ if Miam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
233
+ encoded = JSON.pretty_generate(policy_document)
234
+ encoded = encoded.gsub(/^\s+/m, '').strip
235
+ end
236
+
237
+ if Miam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
238
+ encoded = JSON.dump(policy_document)
239
+ end
240
+
241
+ encoded
242
+ end
243
+ end
244
+
245
+ def unless_dry_run
246
+ yield unless @options[:dry_run]
247
+ end
248
+ end
@@ -0,0 +1,9 @@
1
+ class Miam::DSL
2
+ def self.convert(exported, options = {})
3
+ Miam::DSL::Converter.convert(exported, options)
4
+ end
5
+
6
+ def self.parse(dsl, path, options = {})
7
+ Miam::DSL::Context.eval(dsl, path, options).result
8
+ end
9
+ end
@@ -0,0 +1,52 @@
1
+ class Miam::DSL::Context
2
+ def self.eval(dsl, path, options = {})
3
+ self.new(path, options) {
4
+ eval(dsl, binding, path)
5
+ }
6
+ end
7
+
8
+ attr_reader :result
9
+
10
+ def initialize(path, options = {}, &block)
11
+ @path = path
12
+ @options = options
13
+ @result = {:users => {}, :groups => {}}
14
+ instance_eval(&block)
15
+ end
16
+
17
+ private
18
+
19
+ def require(file)
20
+ iamfile = (file =~ %r|\A/|) ? file : File.expand_path(File.join(File.dirname(@path), file))
21
+
22
+ if File.exist?(iamfile)
23
+ instance_eval(File.read(iamfile), iamfile)
24
+ elsif File.exist?(iamfile + '.rb')
25
+ instance_eval(File.read(iamfile + '.rb'), iamfile + '.rb')
26
+ else
27
+ Kernel.require(file)
28
+ end
29
+ end
30
+
31
+ def user(name, user_options = {}, &block)
32
+ name = name.to_s
33
+
34
+ if @result[:users][name]
35
+ raise "User `#{name}` is already defined"
36
+ end
37
+
38
+ attrs = Miam::DSL::Context::User.new(name, &block).result
39
+ @result[:users][name] = user_options.merge(attrs)
40
+ end
41
+
42
+ def group(name, group_options = {}, &block)
43
+ name = name.to_s
44
+
45
+ if @result[:groups][name]
46
+ raise "Group `#{name}` is already defined"
47
+ end
48
+
49
+ attrs = Miam::DSL::Context::Group.new(name, &block).result
50
+ @result[:groups][name] = group_options.merge(attrs)
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ class Miam::DSL::Context::Group
2
+ def initialize(name, &block)
3
+ @name = name
4
+ @result = {:policies => {}}
5
+ instance_eval(&block)
6
+ end
7
+
8
+ attr_reader :result
9
+
10
+ private
11
+
12
+ def policy(name)
13
+ name = name.to_s
14
+
15
+ if @result[:policies][name]
16
+ raise "Group `#{name}` > Policy `#{name}`: already defined"
17
+ end
18
+
19
+ policy_document = yield
20
+
21
+ unless policy_document.kind_of?(Hash)
22
+ raise "Group `#{name}` > Policy `#{name}`: wrong argument type #{policy_document.class} (expected Hash)"
23
+ end
24
+
25
+ @result[:policies][name] = policy_document
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ class Miam::DSL::Context::User
2
+ def initialize(name, &block)
3
+ @name = name
4
+ @result = {:groups => [], :policies => {}}
5
+ instance_eval(&block)
6
+ end
7
+
8
+ attr_reader :result
9
+
10
+ private
11
+
12
+ def login_profile(value)
13
+ @result[:login_profile] = value
14
+ end
15
+
16
+ def groups(*grps)
17
+ @result[:groups].concat(grps.map {|i| i.to_s })
18
+ end
19
+
20
+ def policy(name)
21
+ name = name.to_s
22
+
23
+ if @result[:policies][name]
24
+ raise "User `#{name}` > Policy `#{name}`: already defined"
25
+ end
26
+
27
+ policy_document = yield
28
+
29
+ unless policy_document.kind_of?(Hash)
30
+ raise "User `#{name}` > Policy `#{name}`: wrong argument type #{policy_document.class} (expected Hash)"
31
+ end
32
+
33
+ @result[:policies][name] = policy_document
34
+ end
35
+ end
@@ -0,0 +1,91 @@
1
+ class Miam::DSL::Converter
2
+ def self.convert(exported, options = {})
3
+ self.new(exported, options).convert
4
+ end
5
+
6
+ def initialize(exported, options = {})
7
+ @exported = exported
8
+ @options = options
9
+ end
10
+
11
+ def convert
12
+ [
13
+ output_users(@exported[:users]),
14
+ output_groups(@exported[:groups]),
15
+ ].join("\n")
16
+ end
17
+
18
+ private
19
+
20
+ def output_users(users)
21
+ users.each.sort_by {|k, v| k }.map {|user_name, attrs|
22
+ output_user(user_name, attrs)
23
+ }.join("\n")
24
+ end
25
+
26
+ def output_user(user_name, attrs)
27
+ user_options = {:path => attrs[:path]}
28
+
29
+ <<-EOS
30
+ user #{user_name.inspect}, #{Miam::Utils.unbrace(user_options.inspect)} do
31
+ #{output_login_profile(attrs[:login_profile])}
32
+
33
+ #{output_user_groups(attrs[:groups])}
34
+
35
+ #{output_policies(attrs[:policies])}
36
+ end
37
+ EOS
38
+ end
39
+
40
+ def output_user_groups(groups)
41
+ if groups.empty?
42
+ groups = ['# no group']
43
+ else
44
+ groups = groups.map {|i| i.inspect }
45
+ end
46
+
47
+ groups = "\n " + groups.join(",\n ") + "\n "
48
+ "groups(#{groups})"
49
+ end
50
+
51
+ def output_login_profile(login_profile)
52
+ if login_profile
53
+ "login_profile #{Miam::Utils.unbrace(login_profile.inspect)}"
54
+ else
55
+ '# login_profile :password_reset_required=>true'
56
+ end
57
+ end
58
+
59
+ def output_groups(groups)
60
+ groups.each.sort_by {|k, v| k }.map {|group_name, attrs|
61
+ output_group(group_name, attrs)
62
+ }.join("\n")
63
+ end
64
+
65
+ def output_group(group_name, attrs)
66
+ group_options = {:path => attrs[:path]}
67
+
68
+ <<-EOS
69
+ group #{group_name.inspect}, #{Miam::Utils.unbrace(group_options.inspect)} do
70
+ #{output_policies(attrs[:policies])}
71
+ end
72
+ EOS
73
+ end
74
+
75
+ def output_policies(policies)
76
+ policies.map {|policy_name, policy_document|
77
+ output_policy(policy_name, policy_document)
78
+ }.join("\n\n ").strip
79
+ end
80
+
81
+ def output_policy(policy_name, policy_document)
82
+ policy_document = policy_document.pretty_inspect
83
+ policy_document.gsub!("\n", "\n ").strip!
84
+
85
+ <<-EOS.strip
86
+ policy #{policy_name.inspect} do
87
+ #{policy_document}
88
+ end
89
+ EOS
90
+ end
91
+ end