subiam 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +48 -0
- data/README.md +408 -0
- data/Rakefile +5 -0
- data/bin/subiam +189 -0
- data/lib/subiam/client.rb +565 -0
- data/lib/subiam/driver.rb +466 -0
- data/lib/subiam/dsl/context/group.rb +35 -0
- data/lib/subiam/dsl/context/managed_policy.rb +23 -0
- data/lib/subiam/dsl/context/role.rb +59 -0
- data/lib/subiam/dsl/context/user.rb +43 -0
- data/lib/subiam/dsl/context.rb +101 -0
- data/lib/subiam/dsl/converter.rb +202 -0
- data/lib/subiam/dsl/helper/arn.rb +22 -0
- data/lib/subiam/dsl.rb +9 -0
- data/lib/subiam/exporter.rb +278 -0
- data/lib/subiam/ext/array_ext.rb +13 -0
- data/lib/subiam/ext/hash_ext.rb +41 -0
- data/lib/subiam/ext/string_ext.rb +25 -0
- data/lib/subiam/logger.rb +27 -0
- data/lib/subiam/password_manager.rb +41 -0
- data/lib/subiam/template_helper.rb +20 -0
- data/lib/subiam/utils.rb +31 -0
- data/lib/subiam/version.rb +3 -0
- data/lib/subiam.rb +36 -0
- data/spec/spec_helper.rb +95 -0
- data/spec/subiam/attach_detach_policy_spec.rb +389 -0
- data/spec/subiam/create_spec.rb +271 -0
- data/spec/subiam/custom_managed_policy_spec.rb +232 -0
- data/spec/subiam/delete_spec.rb +549 -0
- data/spec/subiam/hash_ext_spec.rb +61 -0
- data/spec/subiam/ignore_login_profile_spec.rb +73 -0
- data/spec/subiam/rename_spec.rb +476 -0
- data/spec/subiam/style_spec.rb +189 -0
- data/spec/subiam/target_spec.rb +150 -0
- data/spec/subiam/update_spec.rb +911 -0
- data/subiam.gemspec +32 -0
- metadata +251 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
class Subiam::DSL::Context
|
2
|
+
include Subiam::TemplateHelper
|
3
|
+
|
4
|
+
def self.eval(dsl, path, options = {})
|
5
|
+
self.new(path, options) {
|
6
|
+
eval(dsl, binding, path)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :result
|
11
|
+
|
12
|
+
def initialize(path, options = {}, &block)
|
13
|
+
@path = path
|
14
|
+
@options = options
|
15
|
+
@result = {:users => {}, :groups => {}, :roles => {}, :instance_profiles => {}, :policies => {}, :target => nil}
|
16
|
+
|
17
|
+
@context = Hashie::Mash.new(
|
18
|
+
:path => path,
|
19
|
+
:options => options,
|
20
|
+
:templates => {}
|
21
|
+
)
|
22
|
+
|
23
|
+
instance_eval(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def template(name, &block)
|
27
|
+
@context.templates[name.to_s] = block
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def import(file)
|
33
|
+
iamfile = (file =~ %r|\A/|) ? file : File.expand_path(File.join(File.dirname(@path), file))
|
34
|
+
|
35
|
+
if File.exist?(iamfile)
|
36
|
+
instance_eval(File.read(iamfile), iamfile)
|
37
|
+
elsif File.exist?(iamfile + '.rb')
|
38
|
+
instance_eval(File.read(iamfile + '.rb'), iamfile + '.rb')
|
39
|
+
else
|
40
|
+
raise("File: #{iamfile} or #{iamfile + '.rb'} not found.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def target(regexp)
|
45
|
+
@result[:target] = regexp
|
46
|
+
end
|
47
|
+
|
48
|
+
def user(name, user_options = {}, &block)
|
49
|
+
name = name.to_s
|
50
|
+
|
51
|
+
if @result[:users][name]
|
52
|
+
raise "User `#{name}` is already defined"
|
53
|
+
end
|
54
|
+
|
55
|
+
attrs = Subiam::DSL::Context::User.new(@context, name, &block).result
|
56
|
+
@result[:users][name] = user_options.merge(attrs)
|
57
|
+
end
|
58
|
+
|
59
|
+
def group(name, group_options = {}, &block)
|
60
|
+
name = name.to_s
|
61
|
+
|
62
|
+
if @result[:groups][name]
|
63
|
+
raise "Group `#{name}` is already defined"
|
64
|
+
end
|
65
|
+
|
66
|
+
attrs = Subiam::DSL::Context::Group.new(@context, name, &block).result
|
67
|
+
@result[:groups][name] = group_options.merge(attrs)
|
68
|
+
end
|
69
|
+
|
70
|
+
def role(name, role_options = {}, &block)
|
71
|
+
name = name.to_s
|
72
|
+
|
73
|
+
if @result[:roles][name]
|
74
|
+
raise "Role `#{name}` is already defined"
|
75
|
+
end
|
76
|
+
|
77
|
+
attrs = Subiam::DSL::Context::Role.new(@context, name, &block).result
|
78
|
+
@result[:roles][name] = role_options.merge(attrs)
|
79
|
+
end
|
80
|
+
|
81
|
+
def instance_profile(name, instance_profile_options = {}, &block)
|
82
|
+
name = name.to_s
|
83
|
+
|
84
|
+
if @result[:instance_profiles][name]
|
85
|
+
raise "instance_profile `#{name}` is already defined"
|
86
|
+
end
|
87
|
+
|
88
|
+
@result[:instance_profiles][name] = instance_profile_options
|
89
|
+
end
|
90
|
+
|
91
|
+
def managed_policy(name, policy_options = {}, &block)
|
92
|
+
name = name.to_s
|
93
|
+
|
94
|
+
if @result[:policies][name]
|
95
|
+
raise "ManagedPolicy `#{name}` is already defined"
|
96
|
+
end
|
97
|
+
|
98
|
+
attrs = Subiam::DSL::Context::ManagedPolicy.new(@context, name, &block).result
|
99
|
+
@result[:policies][name] = policy_options.merge(attrs)
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
class Subiam::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
|
+
output_roles(@exported[:roles]),
|
16
|
+
output_instance_profiles(@exported[:instance_profiles]),
|
17
|
+
output_managed_policies(@exported[:policies]),
|
18
|
+
].join("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def output_users(users)
|
24
|
+
users.each.sort_by {|k, v| k }.map {|user_name, attrs|
|
25
|
+
next unless target_matched?(user_name)
|
26
|
+
output_user(user_name, attrs)
|
27
|
+
}.select {|i| i }.join("\n")
|
28
|
+
end
|
29
|
+
|
30
|
+
def output_user(user_name, attrs)
|
31
|
+
user_options = {:path => attrs[:path]}
|
32
|
+
|
33
|
+
<<-EOS
|
34
|
+
user #{user_name.inspect}, #{Subiam::Utils.unbrace(user_options.inspect)} do
|
35
|
+
#{output_login_profile(attrs[:login_profile])}
|
36
|
+
|
37
|
+
#{output_user_groups(attrs[:groups])}
|
38
|
+
|
39
|
+
#{output_policies(attrs[:policies])}
|
40
|
+
|
41
|
+
#{output_attached_managed_policies(attrs[:attached_managed_policies])}
|
42
|
+
end
|
43
|
+
EOS
|
44
|
+
end
|
45
|
+
|
46
|
+
def output_user_groups(groups)
|
47
|
+
if groups.empty?
|
48
|
+
groups = ['# no group']
|
49
|
+
else
|
50
|
+
groups = groups.map {|i| i.inspect }
|
51
|
+
end
|
52
|
+
|
53
|
+
groups = "\n " + groups.join(",\n ") + "\n "
|
54
|
+
"groups(#{groups})"
|
55
|
+
end
|
56
|
+
|
57
|
+
def output_login_profile(login_profile)
|
58
|
+
if login_profile
|
59
|
+
"login_profile #{Subiam::Utils.unbrace(login_profile.inspect)}"
|
60
|
+
else
|
61
|
+
'# login_profile :password_reset_required=>true'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def output_groups(groups)
|
66
|
+
groups.each.sort_by {|k, v| k }.map {|group_name, attrs|
|
67
|
+
next unless target_matched?(group_name)
|
68
|
+
output_group(group_name, attrs)
|
69
|
+
}.select {|i| i }.join("\n")
|
70
|
+
end
|
71
|
+
|
72
|
+
def output_group(group_name, attrs)
|
73
|
+
group_options = {:path => attrs[:path]}
|
74
|
+
|
75
|
+
<<-EOS
|
76
|
+
group #{group_name.inspect}, #{Subiam::Utils.unbrace(group_options.inspect)} do
|
77
|
+
#{output_policies(attrs[:policies])}
|
78
|
+
|
79
|
+
#{output_attached_managed_policies(attrs[:attached_managed_policies])}
|
80
|
+
end
|
81
|
+
EOS
|
82
|
+
end
|
83
|
+
|
84
|
+
def output_roles(roles)
|
85
|
+
roles.each.sort_by {|k, v| k }.map {|role_name, attrs|
|
86
|
+
next unless target_matched?(role_name)
|
87
|
+
output_role(role_name, attrs)
|
88
|
+
}.select {|i| i }.join("\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def output_role(role_name, attrs)
|
92
|
+
role_options = {:path => attrs[:path]}
|
93
|
+
|
94
|
+
<<-EOS
|
95
|
+
role #{role_name.inspect}, #{Subiam::Utils.unbrace(role_options.inspect)} do
|
96
|
+
#{output_role_instance_profiles(attrs[:instance_profiles])}
|
97
|
+
|
98
|
+
#{output_assume_role_policy_document(attrs[:assume_role_policy_document])}
|
99
|
+
|
100
|
+
#{output_policies(attrs[:policies])}
|
101
|
+
|
102
|
+
#{output_attached_managed_policies(attrs[:attached_managed_policies])}
|
103
|
+
end
|
104
|
+
EOS
|
105
|
+
end
|
106
|
+
|
107
|
+
def output_role_instance_profiles(instance_profiles)
|
108
|
+
if instance_profiles.empty?
|
109
|
+
instance_profiles = ['# no instance_profile']
|
110
|
+
else
|
111
|
+
instance_profiles = instance_profiles.map {|i| i.inspect }
|
112
|
+
end
|
113
|
+
|
114
|
+
instance_profiles = "\n " + instance_profiles.join(",\n ") + "\n "
|
115
|
+
"instance_profiles(#{instance_profiles})"
|
116
|
+
end
|
117
|
+
|
118
|
+
def output_instance_profiles(instance_profiles)
|
119
|
+
instance_profiles.each.sort_by {|k, v| k }.map {|instance_profile_name, attrs|
|
120
|
+
next unless target_matched?(instance_profile_name)
|
121
|
+
output_instance_profile(instance_profile_name, attrs)
|
122
|
+
}.select {|i| i }.join("\n")
|
123
|
+
end
|
124
|
+
|
125
|
+
def output_assume_role_policy_document(assume_role_policy_document)
|
126
|
+
assume_role_policy_document = assume_role_policy_document.pretty_inspect
|
127
|
+
assume_role_policy_document.gsub!("\n", "\n ").strip!
|
128
|
+
|
129
|
+
<<-EOS.strip
|
130
|
+
assume_role_policy_document do
|
131
|
+
#{assume_role_policy_document}
|
132
|
+
end
|
133
|
+
EOS
|
134
|
+
end
|
135
|
+
|
136
|
+
def output_instance_profile(instance_profile_name, attrs)
|
137
|
+
instance_profile_options = {:path => attrs[:path]}
|
138
|
+
|
139
|
+
<<-EOS
|
140
|
+
instance_profile #{instance_profile_name.inspect}, #{Subiam::Utils.unbrace(instance_profile_options.inspect)}
|
141
|
+
EOS
|
142
|
+
end
|
143
|
+
|
144
|
+
def output_policies(policies)
|
145
|
+
if policies.empty?
|
146
|
+
"# no policy"
|
147
|
+
else
|
148
|
+
policies.map {|policy_name, policy_document|
|
149
|
+
output_policy(policy_name, policy_document)
|
150
|
+
}.join("\n\n ").strip
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def output_policy(policy_name, policy_document)
|
155
|
+
policy_document = policy_document.pretty_inspect
|
156
|
+
policy_document.gsub!("\n", "\n ").strip!
|
157
|
+
|
158
|
+
<<-EOS.strip
|
159
|
+
policy #{policy_name.inspect} do
|
160
|
+
#{policy_document}
|
161
|
+
end
|
162
|
+
EOS
|
163
|
+
end
|
164
|
+
|
165
|
+
def output_attached_managed_policies(attached_managed_policies)
|
166
|
+
if attached_managed_policies.empty?
|
167
|
+
attached_managed_policies = ['# attached_managed_policy']
|
168
|
+
else
|
169
|
+
attached_managed_policies = attached_managed_policies.map {|i| i.inspect }
|
170
|
+
end
|
171
|
+
|
172
|
+
attached_managed_policies = "\n " + attached_managed_policies.join(",\n ") + "\n "
|
173
|
+
"attached_managed_policies(#{attached_managed_policies})"
|
174
|
+
end
|
175
|
+
|
176
|
+
def output_managed_policies(policies)
|
177
|
+
policies.each.sort_by {|k, v| k }.map {|policy_name, attrs|
|
178
|
+
next unless target_matched?(policy_name)
|
179
|
+
output_managed_policy(policy_name, attrs)
|
180
|
+
}.select {|i| i }.join("\n")
|
181
|
+
end
|
182
|
+
|
183
|
+
def output_managed_policy(policy_name, attrs)
|
184
|
+
policy_options = {:path => attrs[:path]}
|
185
|
+
policy_document = attrs[:document].pretty_inspect
|
186
|
+
policy_document.gsub!("\n", "\n ").strip!
|
187
|
+
|
188
|
+
<<-EOS
|
189
|
+
managed_policy #{policy_name.inspect}, #{Subiam::Utils.unbrace(policy_options.inspect)} do
|
190
|
+
#{policy_document}
|
191
|
+
end
|
192
|
+
EOS
|
193
|
+
end
|
194
|
+
|
195
|
+
def target_matched?(name)
|
196
|
+
if @options[:target]
|
197
|
+
name =~ @options[:target]
|
198
|
+
else
|
199
|
+
true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Subiam::DSL::Helper
|
2
|
+
module Arn
|
3
|
+
private
|
4
|
+
|
5
|
+
def arn_policy_by_aws(name)
|
6
|
+
"arn:aws:iam::aws:policy/#{name}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def arn_policy_by_current_account(name)
|
10
|
+
"arn:aws:iam::#{current_account}:policy/#{name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def current_account
|
14
|
+
if @current_account
|
15
|
+
return @current_account
|
16
|
+
end
|
17
|
+
aws_config = (@context.options && @context.options[:aws_config]) ? @context.options[:aws_config] : {}
|
18
|
+
sts = Aws::STS::Client.new(aws_config)
|
19
|
+
@current_account = sts.get_caller_identity.user_id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/subiam/dsl.rb
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
class Subiam::Exporter
|
3
|
+
AWS_MANAGED_POLICY_PREFIX = 'arn:aws:iam::aws:'
|
4
|
+
|
5
|
+
def self.export(iam, options = {})
|
6
|
+
self.new(iam, options).export
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(iam, options = {})
|
10
|
+
@iam = iam
|
11
|
+
@options = options
|
12
|
+
@mutex = Mutex.new
|
13
|
+
@concurrency = options[:export_concurrency] || 16
|
14
|
+
end
|
15
|
+
|
16
|
+
def export
|
17
|
+
account_authorization_details = get_account_authorization_details
|
18
|
+
|
19
|
+
users = account_authorization_details[:user_detail_list]
|
20
|
+
groups = account_authorization_details[:group_detail_list]
|
21
|
+
roles = account_authorization_details[:role_detail_list]
|
22
|
+
policies = account_authorization_details[:policies]
|
23
|
+
instance_profiles = list_instance_profiles
|
24
|
+
group_users = {}
|
25
|
+
instance_profile_roles = {}
|
26
|
+
|
27
|
+
unless @options[:no_progress]
|
28
|
+
progress_total = users.length + groups.length + roles.length + instance_profiles.length
|
29
|
+
|
30
|
+
@progressbar = ProgressBar.create(
|
31
|
+
:format => ' %bᗧ%i %p%%',
|
32
|
+
:progress_mark => ' ',
|
33
|
+
:remainder_mark => '・',
|
34
|
+
:total => progress_total,
|
35
|
+
:output => $stderr)
|
36
|
+
end
|
37
|
+
|
38
|
+
expected = {
|
39
|
+
:users => export_users(users, group_users),
|
40
|
+
:groups => export_groups(groups),
|
41
|
+
:roles => export_roles(roles, instance_profile_roles),
|
42
|
+
:instance_profiles => export_instance_profiles(instance_profiles),
|
43
|
+
:policies => export_policies(policies),
|
44
|
+
}
|
45
|
+
|
46
|
+
[expected, group_users, instance_profile_roles]
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def export_users(users, group_users)
|
52
|
+
result = {}
|
53
|
+
|
54
|
+
Parallel.each(users, :in_threads => @concurrency) do |user|
|
55
|
+
user_name = user.user_name
|
56
|
+
groups = user.group_list
|
57
|
+
policies = export_user_policies(user)
|
58
|
+
login_profile = export_login_profile(user_name)
|
59
|
+
attached_managed_policies = user.attached_managed_policies.map(&:policy_arn)
|
60
|
+
|
61
|
+
@mutex.synchronize do
|
62
|
+
groups.each do |group_name|
|
63
|
+
group_users[group_name] ||= []
|
64
|
+
group_users[group_name] << user_name
|
65
|
+
end
|
66
|
+
|
67
|
+
result[user_name] = {
|
68
|
+
:path => user.path,
|
69
|
+
:groups => groups,
|
70
|
+
:policies => policies,
|
71
|
+
:attached_managed_policies => attached_managed_policies
|
72
|
+
}
|
73
|
+
|
74
|
+
if login_profile
|
75
|
+
result[user_name][:login_profile] = login_profile
|
76
|
+
end
|
77
|
+
|
78
|
+
progress
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def export_user_policies(user)
|
86
|
+
result = {}
|
87
|
+
|
88
|
+
user.user_policy_list.each do |policy|
|
89
|
+
document = CGI.unescape(policy.policy_document)
|
90
|
+
result[policy.policy_name] = JSON.parse(document)
|
91
|
+
end
|
92
|
+
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
def export_login_profile(user_name)
|
97
|
+
begin
|
98
|
+
resp = @iam.get_login_profile(:user_name => user_name)
|
99
|
+
{:password_reset_required => resp.login_profile.password_reset_required}
|
100
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def export_groups(groups)
|
106
|
+
result = {}
|
107
|
+
|
108
|
+
Parallel.each(groups, :in_threads => @concurrency) do |group|
|
109
|
+
group_name = group.group_name
|
110
|
+
policies = export_group_policies(group)
|
111
|
+
attached_managed_policies = group.attached_managed_policies.map(&:policy_arn)
|
112
|
+
|
113
|
+
@mutex.synchronize do
|
114
|
+
result[group_name] = {
|
115
|
+
:path => group.path,
|
116
|
+
:policies => policies,
|
117
|
+
:attached_managed_policies => attached_managed_policies,
|
118
|
+
}
|
119
|
+
|
120
|
+
progress
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
result
|
125
|
+
end
|
126
|
+
|
127
|
+
def export_group_policies(group)
|
128
|
+
result = {}
|
129
|
+
|
130
|
+
group.group_policy_list.each do |policy|
|
131
|
+
document = CGI.unescape(policy.policy_document)
|
132
|
+
result[policy.policy_name] = JSON.parse(document)
|
133
|
+
end
|
134
|
+
|
135
|
+
result
|
136
|
+
end
|
137
|
+
|
138
|
+
def export_roles(roles, instance_profile_roles)
|
139
|
+
result = {}
|
140
|
+
|
141
|
+
Parallel.each(roles, :in_threads => @concurrency) do |role|
|
142
|
+
role_name = role.role_name
|
143
|
+
instance_profiles = role.instance_profile_list.map {|i| i.instance_profile_name }
|
144
|
+
policies = export_role_policies(role)
|
145
|
+
attached_managed_policies = role.attached_managed_policies.map(&:policy_arn)
|
146
|
+
|
147
|
+
@mutex.synchronize do
|
148
|
+
instance_profiles.each do |instance_profile_name|
|
149
|
+
instance_profile_roles[instance_profile_name] ||= []
|
150
|
+
instance_profile_roles[instance_profile_name] << role_name
|
151
|
+
end
|
152
|
+
|
153
|
+
document = CGI.unescape(role.assume_role_policy_document)
|
154
|
+
|
155
|
+
result[role_name] = {
|
156
|
+
:path => role.path,
|
157
|
+
:assume_role_policy_document => JSON.parse(document),
|
158
|
+
:instance_profiles => instance_profiles,
|
159
|
+
:policies => policies,
|
160
|
+
:attached_managed_policies => attached_managed_policies,
|
161
|
+
}
|
162
|
+
|
163
|
+
progress
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
170
|
+
def export_role_policies(role)
|
171
|
+
result = {}
|
172
|
+
|
173
|
+
role.role_policy_list.each do |policy|
|
174
|
+
document = CGI.unescape(policy.policy_document)
|
175
|
+
result[policy.policy_name] = JSON.parse(document)
|
176
|
+
end
|
177
|
+
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
def export_instance_profiles(instance_profiles)
|
182
|
+
result = {}
|
183
|
+
|
184
|
+
Parallel.each(instance_profiles, :in_threads => @concurrency) do |instance_profile|
|
185
|
+
instance_profile_name = instance_profile.instance_profile_name
|
186
|
+
|
187
|
+
@mutex.synchronize do
|
188
|
+
result[instance_profile_name] = {
|
189
|
+
:path => instance_profile.path,
|
190
|
+
}
|
191
|
+
|
192
|
+
progress
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
result
|
197
|
+
end
|
198
|
+
|
199
|
+
def export_policies(policies)
|
200
|
+
result = {}
|
201
|
+
|
202
|
+
Parallel.each(policies, :in_threads => @concurrency) do |policy|
|
203
|
+
if policy.arn.start_with?(AWS_MANAGED_POLICY_PREFIX)
|
204
|
+
next
|
205
|
+
end
|
206
|
+
|
207
|
+
policy_name = policy.policy_name
|
208
|
+
document = export_policy_document(policy)
|
209
|
+
|
210
|
+
result[policy_name] = {
|
211
|
+
:path => policy.path,
|
212
|
+
:document => document,
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
result
|
217
|
+
end
|
218
|
+
|
219
|
+
def export_policy_document(policy)
|
220
|
+
policy_version = nil
|
221
|
+
|
222
|
+
policy_version_list = policy.policy_version_list.sort_by do |pv|
|
223
|
+
pv.version_id[1..-1].to_i
|
224
|
+
end
|
225
|
+
|
226
|
+
policy_version_list.each do |pv|
|
227
|
+
policy_version = pv
|
228
|
+
|
229
|
+
if pv.is_default_version
|
230
|
+
break
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
document = CGI.unescape(policy_version.document)
|
235
|
+
JSON.parse(document)
|
236
|
+
end
|
237
|
+
|
238
|
+
def list_instance_profiles
|
239
|
+
@iam.list_instance_profiles.map {|resp|
|
240
|
+
resp.instance_profiles.to_a
|
241
|
+
}.flatten
|
242
|
+
end
|
243
|
+
|
244
|
+
def get_account_authorization_details
|
245
|
+
account_authorization_details = {}
|
246
|
+
|
247
|
+
unless @options[:no_progress]
|
248
|
+
progressbar = ProgressBar.create(:title => 'Loading', :total => nil, :output => $stderr)
|
249
|
+
end
|
250
|
+
|
251
|
+
keys = [
|
252
|
+
:user_detail_list,
|
253
|
+
:group_detail_list,
|
254
|
+
:role_detail_list,
|
255
|
+
:policies,
|
256
|
+
]
|
257
|
+
|
258
|
+
keys.each do |key|
|
259
|
+
account_authorization_details[key] = []
|
260
|
+
end
|
261
|
+
|
262
|
+
@iam.get_account_authorization_details.each do |resp|
|
263
|
+
keys.each do |key|
|
264
|
+
account_authorization_details[key].concat(resp[key])
|
265
|
+
|
266
|
+
unless @options[:no_progress]
|
267
|
+
progressbar.increment
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
account_authorization_details
|
273
|
+
end
|
274
|
+
|
275
|
+
def progress
|
276
|
+
@progressbar.increment if @progressbar
|
277
|
+
end
|
278
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Hash
|
2
|
+
def sort_array!
|
3
|
+
keys.each do |key|
|
4
|
+
value = self[key]
|
5
|
+
self[key] = sort_array0(value)
|
6
|
+
end
|
7
|
+
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def keys_to_s_recursive
|
12
|
+
new_one = {}
|
13
|
+
self.each do |key, elem|
|
14
|
+
if elem.respond_to? :keys_to_s_recursive
|
15
|
+
new_one[key.to_s] = elem.keys_to_s_recursive
|
16
|
+
next
|
17
|
+
end
|
18
|
+
new_one[key.to_s] = elem
|
19
|
+
end
|
20
|
+
new_one
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def sort_array0(value)
|
26
|
+
case value
|
27
|
+
when Hash
|
28
|
+
new_value = {}
|
29
|
+
|
30
|
+
value.each do |k, v|
|
31
|
+
new_value[k] = sort_array0(v)
|
32
|
+
end
|
33
|
+
|
34
|
+
new_value
|
35
|
+
when Array
|
36
|
+
value.map {|v| sort_array0(v) }.sort_by(&:to_s)
|
37
|
+
else
|
38
|
+
value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class String
|
2
|
+
@@colorize = false
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def colorize=(value)
|
6
|
+
@@colorize = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def colorize
|
10
|
+
@@colorize
|
11
|
+
end
|
12
|
+
end # of class methods
|
13
|
+
|
14
|
+
Term::ANSIColor::Attribute.named_attributes.map do |attribute|
|
15
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
16
|
+
def #{attribute.name}
|
17
|
+
if @@colorize
|
18
|
+
Term::ANSIColor.send(#{attribute.name.inspect}, self)
|
19
|
+
else
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
end
|