chef_fixie 0.3.0 → 1.0.2

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.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/bin/chef_fixie +1 -1
  3. data/doc/BulkFixup.md +1 -1
  4. data/doc/CommonTasks.md +14 -3
  5. data/lib/chef_fixie.rb +7 -7
  6. data/lib/chef_fixie/authz_mapper.rb +26 -28
  7. data/lib/chef_fixie/authz_objects.rb +44 -41
  8. data/lib/chef_fixie/bulk_edit_permissions.rb +24 -20
  9. data/lib/chef_fixie/check_org_associations.rb +56 -58
  10. data/lib/chef_fixie/config.rb +58 -24
  11. data/lib/chef_fixie/console.rb +15 -10
  12. data/lib/chef_fixie/context.rb +2 -4
  13. data/lib/chef_fixie/sql.rb +12 -12
  14. data/lib/chef_fixie/sql_objects.rb +49 -38
  15. data/lib/chef_fixie/utility_helpers.rb +13 -9
  16. data/lib/chef_fixie/version.rb +1 -1
  17. data/spec/chef_fixie/acl_spec.rb +23 -25
  18. data/spec/chef_fixie/assoc_invite_spec.rb +5 -8
  19. data/spec/chef_fixie/check_org_associations_spec.rb +14 -17
  20. data/spec/chef_fixie/groups_spec.rb +7 -11
  21. data/spec/chef_fixie/org_spec.rb +4 -5
  22. data/spec/chef_fixie/orgs_spec.rb +6 -9
  23. data/spec/spec_helper.rb +5 -6
  24. metadata +18 -84
  25. data/bin/bundler +0 -16
  26. data/bin/chef-apply +0 -16
  27. data/bin/chef-client +0 -16
  28. data/bin/chef-shell +0 -16
  29. data/bin/chef-solo +0 -16
  30. data/bin/chef-zero +0 -16
  31. data/bin/coderay +0 -16
  32. data/bin/edit_json.rb +0 -16
  33. data/bin/erubis +0 -16
  34. data/bin/ffi-yajl-bench +0 -16
  35. data/bin/fixie~ +0 -231
  36. data/bin/htmldiff +0 -16
  37. data/bin/knife +0 -16
  38. data/bin/ldiff +0 -16
  39. data/bin/net-dhcp +0 -16
  40. data/bin/ohai +0 -16
  41. data/bin/prettify_json.rb +0 -16
  42. data/bin/pry +0 -16
  43. data/bin/rackup +0 -16
  44. data/bin/rake +0 -16
  45. data/bin/rdoc +0 -16
  46. data/bin/restclient +0 -16
  47. data/bin/ri +0 -16
  48. data/bin/rspec +0 -16
  49. data/bin/s3sh +0 -16
  50. data/bin/sequel +0 -16
  51. data/bin/serverspec-init +0 -16
  52. data/doc/AccessingSQL.md~ +0 -32
  53. data/doc/BulkFixup.md~ +0 -28
  54. data/doc/CommonTasks.md~ +0 -0
  55. data/doc/GETTING_STARTED.md~ +0 -6
  56. data/spec/chef_fixie/assoc_invite_spec.rb~ +0 -26
  57. data/spec/chef_fixie/check_org_associations_spec.rb~ +0 -34
  58. data/spec/chef_fixie/org_spec.rb~ +0 -53
@@ -18,45 +18,55 @@
18
18
  # Author: Mark Anderson <mark@chef.io>
19
19
  #
20
20
 
21
- require_relative 'config'
22
- require_relative 'authz_objects'
23
- require_relative 'authz_mapper'
24
- require_relative 'utility_helpers'
21
+ require_relative "config"
22
+ require_relative "authz_objects"
23
+ require_relative "authz_mapper"
24
+ require_relative "utility_helpers"
25
25
 
26
26
  module ChefFixie
27
27
  module CheckOrgAssociations
28
28
  def self.orgs
29
29
  @orgs ||= ChefFixie::Sql::Orgs.new
30
30
  end
31
+
31
32
  def self.users
32
33
  @users ||= ChefFixie::Sql::Users.new
33
34
  end
35
+
34
36
  def self.assocs
35
37
  @assocs ||= ChefFixie::Sql::Associations.new
36
38
  end
39
+
37
40
  def self.invites
38
41
  invites ||= ChefFixie::Sql::Invites.new
39
42
  end
40
43
 
41
44
  def self.make_user(user)
42
45
  if user.is_a?(String)
43
- return users[user]
46
+ users[user]
44
47
  elsif user.is_a?(ChefFixie::Sql::User)
45
- return user
48
+ user
46
49
  else
47
50
  raise "Expected a user, got a #{user.class}"
48
51
  end
49
52
  end
53
+
50
54
  def self.make_org(org)
51
55
  if org.is_a?(String)
52
- return orgs[org]
56
+ orgs[org]
53
57
  elsif org.is_a?(ChefFixie::Sql::Org)
54
- return org
58
+ org
55
59
  else
56
60
  raise "Expected an org, got a #{org.class}"
57
61
  end
58
62
  end
59
63
 
64
+ def usag_for_user(org, user)
65
+ user = make_user(user)
66
+ org = make_org(org)
67
+ org.groups[user.id]
68
+ end
69
+
60
70
  def self.check_association(org, user, global_admins = nil)
61
71
  # magic to make usage easier
62
72
  org = make_org(org)
@@ -78,7 +88,7 @@ module ChefFixie
78
88
  return :user_not_in_usag
79
89
  end
80
90
 
81
- if !org.groups['users'].member?(usag)
91
+ if !org.groups["users"].member?(usag)
82
92
  return :usag_not_in_users
83
93
  end
84
94
 
@@ -89,7 +99,7 @@ module ChefFixie
89
99
  if invites.by_org_id_user_id(org.id, user.id)
90
100
  return :zombie_invite
91
101
  end
92
- return true
102
+ true
93
103
  end
94
104
 
95
105
  def self.fix_association(org, user, global_admins = nil)
@@ -98,7 +108,7 @@ module ChefFixie
98
108
  user = users[user] if user.is_a?(String)
99
109
  global_admins ||= org.global_admins
100
110
 
101
- failure = check_association(org,user,global_admins)
111
+ failure = check_association(org, user, global_admins)
102
112
 
103
113
  case failure
104
114
  when true
@@ -108,14 +118,14 @@ module ChefFixie
108
118
  usag.group_add(user)
109
119
  when :usag_not_in_users
110
120
  usag = org.groups[user.id]
111
- org.groups['users'].group_add(usag)
121
+ org.groups["users"].group_add(usag)
112
122
  when :global_admins_lacks_read
113
123
  user.ace_add(:read, global_admins)
114
124
  else
115
125
  puts "#{org.name} #{user.name} can't fix problem #{failure} yet"
116
126
  return false
117
127
  end
118
- return true
128
+ true
119
129
  end
120
130
 
121
131
  def self.check_associations(org)
@@ -133,56 +143,54 @@ module ChefFixie
133
143
  users_assoc = assocs.by_org_id(org.id).all(:all)
134
144
  users_invite = invites.by_org_id(org.id).all(:all)
135
145
 
136
- user_ids = users_assoc.map {|a| a.user_id }
137
- users_in_org = user_ids.map {|i| users.by_id(i).all.first }
138
- usernames = users_in_org.map {|u| u.name }
139
-
146
+ user_ids = users_assoc.map { |a| a.user_id }
147
+ users_in_org = user_ids.map { |i| users.by_id(i).all.first }
148
+ usernames = users_in_org.map { |u| u.name }
140
149
 
141
150
  # check that users aren't both invited and associated
142
- invited_ids = users_invite.map {|a| a.user_id }
151
+ invited_ids = users_invite.map { |a| a.user_id }
143
152
  overlap_ids = user_ids & invited_ids
144
153
 
145
154
  if !overlap_ids.empty?
146
- overlap_names = overlap_ids.map {|i| users.by_id(i).all.first.name rescue "#{i}" }
147
- puts "#{orgname} users both associated and invited: #{overlap_names.join(', ') }"
155
+ overlap_names = overlap_ids.map { |i| users.by_id(i).all.first.name rescue "#{i}" }
156
+ puts "#{orgname} users both associated and invited: #{overlap_names.join(', ')}"
148
157
  success = false
149
158
  end
150
159
 
151
160
  # Check that we don't have zombie USAGs left around (not 100% reliable)
152
161
  # because someone could create a group that looks like a USAG
153
162
  possible_usags = org.groups.list(:all) - user_ids
154
- usags = possible_usags.select {|n| n =~ /^\h+{20}$/ }
163
+ usags = possible_usags.select { |n| n =~ /^\h+{20}$/ }
155
164
  if !usags.empty?
156
- puts "#{orgname} Suspicious USAGS without associated user #{usags.join(', ') }"
165
+ puts "#{orgname} Suspicious USAGS without associated user #{usags.join(', ')}"
157
166
  end
158
167
 
159
168
  # Check group membership for sanity
160
- success &= check_group(org, 'billing-admins', usernames)
161
- success &= check_group(org, 'admins', usernames)
169
+ success &= check_group(org, "billing-admins", usernames)
170
+ success &= check_group(org, "admins", usernames)
162
171
 
163
172
  # TODO check for non-usags in users!
164
- users_members = org.groups['users'].group
165
- users_actors = users_members['actors'] - [[:global, "pivotal"]]
173
+ users_members = org.groups["users"].group
174
+ users_actors = users_members["actors"] - [[:global, "pivotal"]]
166
175
  if !users_actors.empty?
167
176
  puts "#{orgname} has actors in it's users group #{users_actors}"
168
177
  end
169
- non_usags = users_members['groups'].map {|g| g[1] } - user_ids
178
+ non_usags = users_members["groups"].map { |g| g[1] } - user_ids
170
179
  if !non_usags.empty?
171
180
  puts "#{orgname} warning: has non usags in it's users group #{non_usags.join(', ')}"
172
181
  end
173
182
 
174
-
175
183
  # Check individual associations
176
184
  users_in_org.each do |user|
177
- result = self.check_association(org,user,global_admins)
178
- if (result != true)
185
+ result = check_association(org, user, global_admins)
186
+ if result != true
179
187
  puts "Org #{orgname} Association check failed for #{user.name} #{result}"
180
188
  success = false
181
189
  end
182
190
  end
183
191
 
184
192
  puts "Org #{orgname} is #{success ? 'ok' : 'bad'} (#{users_in_org.count} users)"
185
- return success
193
+ success
186
194
  end
187
195
 
188
196
  # expect at least one current user to be in admins and billing admins
@@ -192,50 +200,40 @@ module ChefFixie
192
200
  puts "#{orgname} Missing group #{groupname}"
193
201
  return :no_such_group
194
202
  end
195
- actors = g.group['actors'].map {|x| x[1] }
203
+ actors = g.group["actors"].map { |x| x[1] }
196
204
  live = actors & users
197
205
 
198
206
  if live.count == 0
199
207
  puts "Org #{org.name} has no active users in #{groupname}"
200
208
  return false
201
209
  end
202
- return true
210
+ true
203
211
  end
204
212
 
205
-
206
- ## TODO: Port this
207
213
  def self.remove_association(org, user)
208
214
  # magic to make usage easier
209
- org = orgs[org] if org.is_a?(String)
210
- user = users[user] if user.is_a?(String)
215
+ org = make_org(org)
216
+ user = make_user(user)
211
217
 
212
218
  # remove USAG
213
- delete_usag_for_user(orgname,username)
219
+ usag = org.groups[user.id]
220
+ usag.delete if usag
214
221
 
215
- # remove read ACE
216
- u_aid = user.authz_id
217
- ga = OrgMapper::CouchSupport.doc_from_view("#{orgname}_global_admins", "#{Group}/by_groupname")
218
- ga_aid = user_to_authz(ga["_id"])
222
+ # remove from any groups they are in
223
+ org.groups.all(:all).each do |g|
224
+ g.group_delete(user) if g.member?(user)
225
+ end
219
226
 
220
- read_ace = OrgMapper::RawAuth.get("actors/#{u_aid}/acl/read")
221
- read_ace["groups"] -= [ga_aid]
222
- OrgMapper::RawAuth.put("actors/#{u_aid}/acl/read", read_ace)
227
+ # remove read ACE
228
+ user.ace_delete(:read, org.global_admins)
223
229
 
224
230
  # remove association record
231
+ assoc = assocs.by_org_id_user_id(org.id, user.id)
232
+ assoc.delete if assoc
225
233
 
226
- org_assoc = OrgMapper::CouchSupport.associations_for_org(orgname)
227
- doc = org_assoc.select {|x| x[:uid] == user.id}.first
228
-
229
- OrgMapper::CouchSupport.delete_account_doc(doc[:id])
230
-
231
- # clean up excess invites
232
- invites = OrgMapper::CouchSupport.invites_for_org(orgname)
233
- invite_map = invites.inject({}) {|a,e| a[e[:name]] = e; a}
234
-
235
- if invite_map.has_key?(username)
236
- invite = invite_map[username]
237
- OrgMapper::CouchSupport.delete_account_doc(invite[:id])
238
- end
234
+ # remove any invites
235
+ invite = invites.by_org_id_user_id(org.id, user.id)
236
+ invite.delete if invite
239
237
  end
240
238
  end
241
239
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2014-2015 Chef Software Inc.
2
+ # Copyright (c) 2014-2015 Chef Software Inc.
3
3
  # License :: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,9 +18,10 @@
18
18
  #
19
19
  # Much of this code was orginally derived from the orgmapper tool, which had many varied authors.
20
20
 
21
- require 'singleton'
22
- require 'ffi_yajl'
23
- require 'pathname'
21
+ require "singleton"
22
+ require "ffi_yajl"
23
+ require "pathname"
24
+ require "veil"
24
25
 
25
26
  module ChefFixie
26
27
  def self.configure
@@ -29,11 +30,11 @@ module ChefFixie
29
30
 
30
31
  def self.load_config(config_file = nil)
31
32
  if config_file
32
- puts "loading config: #{config_file}..."
33
+ puts "loading config: #{config_file}..." if ChefFixie::Console.started_from_command_line?
33
34
  Kernel.load(config_file)
34
35
  else
35
36
  path = "/etc/opscode"
36
- puts "loading config from #{path}"
37
+ puts "loading config from #{path}" if ChefFixie::Console.started_from_command_line?
37
38
  ChefFixie::Config.instance.load_from_pc(path)
38
39
  end
39
40
  end
@@ -65,7 +66,7 @@ module ChefFixie
65
66
  KEYS = [:authz_uri, :sql_database, :superuser_id, :pivotal_key]
66
67
  KEYS.each { |k| attr_accessor k }
67
68
 
68
- def merge_opts(opts={})
69
+ def merge_opts(opts = {})
69
70
  opts.each do |key, value|
70
71
  send("#{key}=".to_sym, value)
71
72
  end
@@ -83,7 +84,7 @@ module ChefFixie
83
84
  key_len > max ? key_len : max
84
85
  end
85
86
  KEYS.each do |key|
86
- value = send(key) || 'default'
87
+ value = send(key) || "default"
87
88
  txt << "# %#{max_key_len}s: %s" % [key.to_s, value]
88
89
  end
89
90
  txt.join("\n")
@@ -101,26 +102,28 @@ module ChefFixie
101
102
  def load_from_pc(dir = "/etc/opscode")
102
103
  configdir = Pathname.new(dir)
103
104
 
104
- config_files = %w(chef-server-running.json)
105
+ config_files = %w{chef-server-running.json}
105
106
  config = load_json_from_path([configdir], config_files)
106
107
 
107
- authz_config = config['private_chef']['oc_bifrost']
108
- authz_vip = authz_config['vip']
109
- authz_port = authz_config['port']
108
+ secrets = load_secrets_from_path([configdir], %w{private-chef-secrets.json} )
109
+
110
+ authz_config = config["private_chef"]["oc_bifrost"]
111
+ authz_vip = authz_config["vip"]
112
+ authz_port = authz_config["port"]
110
113
  @authz_uri = "http://#{authz_vip}:#{authz_port}"
111
-
112
- @superuser_id = authz_config['superuser_id']
113
-
114
- sql_config = config['private_chef']['postgresql']
115
- erchef_config = config['private_chef']['opscode-erchef']
116
-
117
- sql_user = sql_config['sql_user'] || erchef_config['sql_user']
118
- sql_pw = sql_config['sql_password'] || erchef_config['sql_password']
119
- sql_vip = sql_config['vip']
120
- sql_port = sql_config['port']
121
-
114
+
115
+ @superuser_id = dig(secrets, %w{oc_bifrost superuser_id}) || authz_config["superuser_id"]
116
+
117
+ sql_config = config["private_chef"]["postgresql"]
118
+ erchef_config = config["private_chef"]["opscode-erchef"]
119
+
120
+ sql_user = sql_config["sql_user"] || erchef_config["sql_user"]
121
+ sql_pw = dig(secrets, %w{opscode_erchef sql_password}) || sql_config["sql_password"] || erchef_config["sql_password"]
122
+ sql_vip = sql_config["vip"]
123
+ sql_port = sql_config["port"]
124
+
122
125
  @sql_database = "postgres://#{sql_user}:#{sql_pw}@#{sql_vip}/opscode_chef"
123
-
126
+
124
127
  @pivotal_key = configdir + "pivotal.pem"
125
128
  end
126
129
 
@@ -136,5 +139,36 @@ module ChefFixie
136
139
  end
137
140
  end
138
141
  end
142
+
143
+ def load_secrets_from_path(pathlist, filelist)
144
+ pathlist.each do |path|
145
+ filelist.each do |file|
146
+ configfile = path + file
147
+ if configfile.file?
148
+ data = Veil::CredentialCollection::ChefSecretsFile.from_file(configfile)
149
+ return data
150
+ end
151
+ end
152
+ end
153
+ nil
154
+ end
155
+
156
+ def dig(hash, list)
157
+ if hash.respond_to?(:get)
158
+ hash.get(*list)
159
+ elsif hash.nil?
160
+ nil
161
+ elsif list.empty?
162
+ hash
163
+ else
164
+ element = list.shift
165
+ if hash.has_key?(element)
166
+ dig(hash[element], list)
167
+ else
168
+ nil
169
+ end
170
+ end
171
+ end
172
+
139
173
  end
140
174
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2015 Chef Software Inc.
2
+ # Copyright (c) 2015 Chef Software Inc.
3
3
  # License :: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,18 +18,19 @@
18
18
  #
19
19
  # Much of this code was orginally derived from the orgmapper tool, which had many varied authors.
20
20
 
21
- require 'optparse'
22
- require 'pp'
23
- require 'pry'
21
+ require "optparse"
22
+ require "pp"
23
+ require "pry"
24
24
 
25
- require_relative '../chef_fixie'
26
- require_relative 'context'
25
+ require_relative "../chef_fixie"
26
+ require_relative "context"
27
27
 
28
28
  module ChefFixie
29
29
  module Console
30
30
  extend self
31
31
 
32
32
  def start
33
+ @@started_from_command_line = true
33
34
  configure
34
35
  ChefFixie.setup
35
36
  configure_pry
@@ -46,9 +47,9 @@ module ChefFixie
46
47
  options = {}
47
48
  OptionParser.new do |opt|
48
49
  opt.banner = "Usage: fixie [config] [options]"
49
- opt.on('--authz_uri AUTH_URI', "The URI of the opscode authz service") { |v| options[:authz_uri] =v }
50
- opt.on("--sql_database DATABASE", 'The URI of the opscode_chef database') { |v| options[:sql_database] = v }
51
- opt.on_tail('-h', '--help', 'Show this message') do
50
+ opt.on("--authz_uri AUTH_URI", "The URI of the opscode authz service") { |v| options[:authz_uri] = v }
51
+ opt.on("--sql_database DATABASE", "The URI of the opscode_chef database") { |v| options[:sql_database] = v }
52
+ opt.on_tail("-h", "--help", "Show this message") do
52
53
  puts opt
53
54
  puts "\nExample configuration file:\n\n"
54
55
  puts ChefFixie::Config.instance.example_config
@@ -67,7 +68,7 @@ module ChefFixie
67
68
  Pry.config.history.file = "~/.fixie_history"
68
69
  Pry.config.prompt_name = "fixie"
69
70
  Pry::Commands.block_command("fixie-help", "Show fixie's help") do
70
- output.puts(<<-HALP)
71
+ output.puts(<<-HALP)
71
72
  ** ORGS **
72
73
  * access with ORGS or ORGS
73
74
  * access a specific org: ORGS['orgname']
@@ -87,5 +88,9 @@ HALP
87
88
  end
88
89
  end
89
90
 
91
+ def started_from_command_line?
92
+ @@started_from_command_line == true
93
+ end
94
+
90
95
  end
91
96
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2015 Chef Software Inc.
2
+ # Copyright (c) 2015 Chef Software Inc.
3
3
  # License :: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,9 +18,8 @@
18
18
  #
19
19
  # Much of this code was orginally derived from the orgmapper tool, which had many varied authors.
20
20
 
21
-
22
21
  module ChefFixie
23
- module Context
22
+ module Context
24
23
 
25
24
  def describe_orgs
26
25
  OrgMetrics.org_stats(orgs)
@@ -67,6 +66,5 @@ module ChefFixie
67
66
 
68
67
  ChefFixie::Dissociator.dissociate_user(org, user)
69
68
  end
70
-
71
69
  end
72
70
  end