chef_fixie 0.1.0 → 0.5.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 +5 -5
- data/bin/chef_fixie +2 -2
- data/doc/AccessingSQL.md +33 -1
- data/doc/BulkFixup.md +33 -0
- data/doc/CommonTasks.md +14 -3
- data/lib/chef_fixie.rb +7 -6
- data/lib/chef_fixie/authz_mapper.rb +26 -28
- data/lib/chef_fixie/authz_objects.rb +51 -41
- data/lib/chef_fixie/bulk_edit_permissions.rb +161 -0
- data/lib/chef_fixie/check_org_associations.rb +56 -59
- data/lib/chef_fixie/config.rb +58 -23
- data/lib/chef_fixie/console.rb +17 -12
- data/lib/chef_fixie/context.rb +2 -4
- data/lib/chef_fixie/sql.rb +12 -12
- data/lib/chef_fixie/sql_objects.rb +107 -31
- data/lib/chef_fixie/utility_helpers.rb +13 -9
- data/lib/chef_fixie/version.rb +1 -1
- data/spec/chef_fixie/acl_spec.rb +23 -25
- data/spec/chef_fixie/assoc_invite_spec.rb +5 -8
- data/spec/chef_fixie/check_org_associations_spec.rb +14 -17
- data/spec/chef_fixie/groups_spec.rb +7 -11
- data/spec/chef_fixie/org_spec.rb +4 -5
- data/spec/chef_fixie/orgs_spec.rb +6 -9
- data/spec/spec_helper.rb +5 -6
- metadata +13 -49
- data/bin/bundler +0 -16
- data/bin/chef-apply +0 -16
- data/bin/chef-client +0 -16
- data/bin/chef-shell +0 -16
- data/bin/chef-solo +0 -16
- data/bin/chef-zero +0 -16
- data/bin/coderay +0 -16
- data/bin/edit_json.rb +0 -16
- data/bin/erubis +0 -16
- data/bin/ffi-yajl-bench +0 -16
- data/bin/fixie~ +0 -231
- data/bin/htmldiff +0 -16
- data/bin/knife +0 -16
- data/bin/ldiff +0 -16
- data/bin/net-dhcp +0 -16
- data/bin/ohai +0 -16
- data/bin/prettify_json.rb +0 -16
- data/bin/pry +0 -16
- data/bin/rackup +0 -16
- data/bin/rake +0 -16
- data/bin/rdoc +0 -16
- data/bin/restclient +0 -16
- data/bin/ri +0 -16
- data/bin/rspec +0 -16
- data/bin/s3sh +0 -16
- data/bin/sequel +0 -16
- data/bin/serverspec-init +0 -16
- data/doc/AccessingSQL.md~ +0 -32
- data/doc/BulkFixup.md~ +0 -28
- data/doc/CommonTasks.md~ +0 -0
- data/doc/GETTING_STARTED.md~ +0 -6
- data/spec/chef_fixie/assoc_invite_spec.rb~ +0 -26
- data/spec/chef_fixie/check_org_associations_spec.rb~ +0 -34
- data/spec/chef_fixie/org_spec.rb~ +0 -53
| @@ -0,0 +1,161 @@ | |
| 1 | 
            +
            #
         | 
| 2 | 
            +
            # Copyright (c) 2015 Chef Software Inc.
         | 
| 3 | 
            +
            # License :: Apache License, Version 2.0
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 6 | 
            +
            # you may not use this file except in compliance with the License.
         | 
| 7 | 
            +
            # You may obtain a copy of the License at
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            #     http://www.apache.org/licenses/LICENSE-2.0
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # Unless required by applicable law or agreed to in writing, software
         | 
| 12 | 
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 13 | 
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 14 | 
            +
            # See the License for the specific language governing permissions and
         | 
| 15 | 
            +
            # limitations under the License.
         | 
| 16 | 
            +
            #
         | 
| 17 | 
            +
            # Author: Mark Anderson <mark@chef.io>
         | 
| 18 | 
            +
            #
         | 
| 19 | 
            +
            require "sequel"
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            require_relative "config.rb"
         | 
| 22 | 
            +
            require_relative "authz_objects.rb"
         | 
| 23 | 
            +
            require_relative "authz_mapper.rb"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            require "pp"
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            module ChefFixie
         | 
| 28 | 
            +
              module BulkEditPermissions
         | 
| 29 | 
            +
                def self.orgs
         | 
| 30 | 
            +
                  @orgs ||= ChefFixie::Sql::Orgs.new
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def self.users
         | 
| 34 | 
            +
                  @users ||= ChefFixie::Sql::Users.new
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def self.assocs
         | 
| 38 | 
            +
                  @assocs ||= ChefFixie::Sql::Associations.new
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def self.invites
         | 
| 42 | 
            +
                  invites ||= ChefFixie::Sql::Invites.new
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def self.check_permissions(org)
         | 
| 46 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 47 | 
            +
                  admins = org.groups["admins"].authz_id
         | 
| 48 | 
            +
                  pivotal = users["pivotal"].authz_id
         | 
| 49 | 
            +
                  errors = Hash.new({})
         | 
| 50 | 
            +
                  org.each_authz_object do |object|
         | 
| 51 | 
            +
                    begin
         | 
| 52 | 
            +
                      acl = object.acl_raw
         | 
| 53 | 
            +
                    rescue RestClient::ResourceNotFound => e
         | 
| 54 | 
            +
                      puts "#{object.class} '#{object.name}' id '#{object.id}' missing authz info"
         | 
| 55 | 
            +
                      # pp :object=>object, :e=>e
         | 
| 56 | 
            +
                      next
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    broken_acl = {}
         | 
| 59 | 
            +
                    # the one special case
         | 
| 60 | 
            +
                    acl.each do |k, v|
         | 
| 61 | 
            +
                      list = []
         | 
| 62 | 
            +
                      list << "pivotal" if !v["actors"].member?(pivotal)
         | 
| 63 | 
            +
                      # admins doesn't belong to the billing admins group
         | 
| 64 | 
            +
                      if object.class != ChefFixie::Sql::Group || object.name != "billing-admins"
         | 
| 65 | 
            +
                        list << "admins" if !v["groups"].member?(admins)
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
                      broken_acl[k] = list if !list.empty?
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                    if !broken_acl.empty?
         | 
| 70 | 
            +
                      classname = object.class
         | 
| 71 | 
            +
                      errors[classname] = {} if !errors.has_key?(classname)
         | 
| 72 | 
            +
                      errors[classname][object.name] = broken_acl
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  errors
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                def self.ace_add(list, ace_type, entity)
         | 
| 79 | 
            +
                  list.each do |item|
         | 
| 80 | 
            +
                    if item.respond_to?(:ace_add)
         | 
| 81 | 
            +
                      item.ace_add(ace_type, entity)
         | 
| 82 | 
            +
                    else
         | 
| 83 | 
            +
                      puts "item.class is not a native authz type"
         | 
| 84 | 
            +
                      return nil
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def self.ace_delete(list, ace_type, entity)
         | 
| 90 | 
            +
                  list.each do |item|
         | 
| 91 | 
            +
                    if item.respond_to?(:ace_delete)
         | 
| 92 | 
            +
                      item.ace_delete(ace_type, entity)
         | 
| 93 | 
            +
                    else
         | 
| 94 | 
            +
                      puts "item.class is not a native authz type"
         | 
| 95 | 
            +
                      return nil
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def self.do_all_objects(org)
         | 
| 101 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  containers = org.containers.all(:all)
         | 
| 104 | 
            +
                  # Maybe we should fix up containers first?
         | 
| 105 | 
            +
                  # fix up objects in containers
         | 
| 106 | 
            +
                  containers.each do |container|
         | 
| 107 | 
            +
                    # TODO Write some tests to validate that this stuff
         | 
| 108 | 
            +
                    # works, since it depends on a lot of name magic...
         | 
| 109 | 
            +
                    object_type = container.name.to_sym
         | 
| 110 | 
            +
            #        raise Exception "No such object_type #{object_type}" unless org.respond_to?(object_type)
         | 
| 111 | 
            +
                    objects = org.send(object_type).all(:all)
         | 
| 112 | 
            +
                    if block_given?
         | 
| 113 | 
            +
                      yield objects
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                def self.ace_add_all(org, ace_type, entity)
         | 
| 119 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 120 | 
            +
                  org.each_authz_object_by_class do |objects|
         | 
| 121 | 
            +
                    ace_add(objects, ace_type, entity)
         | 
| 122 | 
            +
                  end
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                def self.ace_delete_all(org, ace_type, entity)
         | 
| 126 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 127 | 
            +
                  org.each_authz_object_by_class do |objects|
         | 
| 128 | 
            +
                    ace_delete(objects, ace_type, entity)
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
                end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def self.add_admin_permissions(org)
         | 
| 133 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 134 | 
            +
                  # rework when ace add takes multiple items...
         | 
| 135 | 
            +
                  admins = org.groups["admins"]
         | 
| 136 | 
            +
                  pivotal = users["pivotal"]
         | 
| 137 | 
            +
                  org.each_authz_object do |object|
         | 
| 138 | 
            +
                    object.ace_add(:all, pivotal)
         | 
| 139 | 
            +
                    if object.class != ChefFixie::Sql::Group || object.name != "billing-admins"
         | 
| 140 | 
            +
                      object.ace_add(:all, admins)
         | 
| 141 | 
            +
                    end
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def self.copy_from_containers(org)
         | 
| 146 | 
            +
                  org = orgs[org] if org.is_a?(String)
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  containers = org.containers.all(:all)
         | 
| 149 | 
            +
                  containers.each do |c|
         | 
| 150 | 
            +
                    # don't mess with containers and groups, they are special
         | 
| 151 | 
            +
                    next if c.name == "containers" || c.name == "groups"
         | 
| 152 | 
            +
                    org.objects_by_container_type(c.name).each do |obj|
         | 
| 153 | 
            +
                      obj.acl_add_from_object(c)
         | 
| 154 | 
            +
                      puts "#{obj.name} from #{c.name}"
         | 
| 155 | 
            +
                    end
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
                  nil
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
            end
         | 
| @@ -18,46 +18,55 @@ | |
| 18 18 | 
             
            # Author: Mark Anderson <mark@chef.io>
         | 
| 19 19 | 
             
            #
         | 
| 20 20 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
            require 'chef_fixie/utility_helpers'
         | 
| 21 | 
            +
            require_relative "config"
         | 
| 22 | 
            +
            require_relative "authz_objects"
         | 
| 23 | 
            +
            require_relative "authz_mapper"
         | 
| 24 | 
            +
            require_relative "utility_helpers"
         | 
| 26 25 |  | 
| 27 26 | 
             
            module ChefFixie
         | 
| 28 27 | 
             
              module CheckOrgAssociations
         | 
| 29 28 | 
             
                def self.orgs
         | 
| 30 29 | 
             
                  @orgs ||= ChefFixie::Sql::Orgs.new
         | 
| 31 30 | 
             
                end
         | 
| 31 | 
            +
             | 
| 32 32 | 
             
                def self.users
         | 
| 33 33 | 
             
                  @users ||= ChefFixie::Sql::Users.new
         | 
| 34 34 | 
             
                end
         | 
| 35 | 
            +
             | 
| 35 36 | 
             
                def self.assocs
         | 
| 36 37 | 
             
                  @assocs ||= ChefFixie::Sql::Associations.new
         | 
| 37 38 | 
             
                end
         | 
| 39 | 
            +
             | 
| 38 40 | 
             
                def self.invites
         | 
| 39 41 | 
             
                  invites ||= ChefFixie::Sql::Invites.new
         | 
| 40 42 | 
             
                end
         | 
| 41 43 |  | 
| 42 44 | 
             
                def self.make_user(user)
         | 
| 43 45 | 
             
                  if user.is_a?(String)
         | 
| 44 | 
            -
                     | 
| 46 | 
            +
                    users[user]
         | 
| 45 47 | 
             
                  elsif user.is_a?(ChefFixie::Sql::User)
         | 
| 46 | 
            -
                     | 
| 48 | 
            +
                    user
         | 
| 47 49 | 
             
                  else
         | 
| 48 50 | 
             
                    raise "Expected a user, got a #{user.class}"
         | 
| 49 51 | 
             
                  end
         | 
| 50 52 | 
             
                end
         | 
| 53 | 
            +
             | 
| 51 54 | 
             
                def self.make_org(org)
         | 
| 52 55 | 
             
                  if org.is_a?(String)
         | 
| 53 | 
            -
                     | 
| 56 | 
            +
                    orgs[org]
         | 
| 54 57 | 
             
                  elsif org.is_a?(ChefFixie::Sql::Org)
         | 
| 55 | 
            -
                     | 
| 58 | 
            +
                    org
         | 
| 56 59 | 
             
                  else
         | 
| 57 60 | 
             
                    raise "Expected an org, got a #{org.class}"
         | 
| 58 61 | 
             
                  end
         | 
| 59 62 | 
             
                end
         | 
| 60 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 | 
            +
             | 
| 61 70 | 
             
                def self.check_association(org, user, global_admins = nil)
         | 
| 62 71 | 
             
                  # magic to make usage easier
         | 
| 63 72 | 
             
                  org = make_org(org)
         | 
| @@ -79,7 +88,7 @@ module ChefFixie | |
| 79 88 | 
             
                    return :user_not_in_usag
         | 
| 80 89 | 
             
                  end
         | 
| 81 90 |  | 
| 82 | 
            -
                  if !org.groups[ | 
| 91 | 
            +
                  if !org.groups["users"].member?(usag)
         | 
| 83 92 | 
             
                    return :usag_not_in_users
         | 
| 84 93 | 
             
                  end
         | 
| 85 94 |  | 
| @@ -90,7 +99,7 @@ module ChefFixie | |
| 90 99 | 
             
                  if invites.by_org_id_user_id(org.id, user.id)
         | 
| 91 100 | 
             
                    return :zombie_invite
         | 
| 92 101 | 
             
                  end
         | 
| 93 | 
            -
                   | 
| 102 | 
            +
                  true
         | 
| 94 103 | 
             
                end
         | 
| 95 104 |  | 
| 96 105 | 
             
                def self.fix_association(org, user, global_admins = nil)
         | 
| @@ -99,7 +108,7 @@ module ChefFixie | |
| 99 108 | 
             
                  user = users[user] if user.is_a?(String)
         | 
| 100 109 | 
             
                  global_admins ||= org.global_admins
         | 
| 101 110 |  | 
| 102 | 
            -
                  failure = check_association(org,user,global_admins)
         | 
| 111 | 
            +
                  failure = check_association(org, user, global_admins)
         | 
| 103 112 |  | 
| 104 113 | 
             
                  case failure
         | 
| 105 114 | 
             
                  when true
         | 
| @@ -109,14 +118,14 @@ module ChefFixie | |
| 109 118 | 
             
                    usag.group_add(user)
         | 
| 110 119 | 
             
                  when :usag_not_in_users
         | 
| 111 120 | 
             
                    usag = org.groups[user.id]
         | 
| 112 | 
            -
                    org.groups[ | 
| 121 | 
            +
                    org.groups["users"].group_add(usag)
         | 
| 113 122 | 
             
                  when :global_admins_lacks_read
         | 
| 114 123 | 
             
                    user.ace_add(:read, global_admins)
         | 
| 115 124 | 
             
                  else
         | 
| 116 125 | 
             
                    puts "#{org.name} #{user.name} can't fix problem #{failure} yet"
         | 
| 117 126 | 
             
                    return false
         | 
| 118 127 | 
             
                  end
         | 
| 119 | 
            -
                   | 
| 128 | 
            +
                  true
         | 
| 120 129 | 
             
                end
         | 
| 121 130 |  | 
| 122 131 | 
             
                def self.check_associations(org)
         | 
| @@ -134,56 +143,54 @@ module ChefFixie | |
| 134 143 | 
             
                  users_assoc = assocs.by_org_id(org.id).all(:all)
         | 
| 135 144 | 
             
                  users_invite = invites.by_org_id(org.id).all(:all)
         | 
| 136 145 |  | 
| 137 | 
            -
                  user_ids = users_assoc.map {|a| a.user_id }
         | 
| 138 | 
            -
                  users_in_org = user_ids.map {|i| users.by_id(i).all.first }
         | 
| 139 | 
            -
                  usernames = users_in_org.map {|u| u.name }
         | 
| 140 | 
            -
             | 
| 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 }
         | 
| 141 149 |  | 
| 142 150 | 
             
                  # check that users aren't both invited and associated
         | 
| 143 | 
            -
                  invited_ids = users_invite.map {|a| a.user_id }
         | 
| 151 | 
            +
                  invited_ids = users_invite.map { |a| a.user_id }
         | 
| 144 152 | 
             
                  overlap_ids = user_ids & invited_ids
         | 
| 145 153 |  | 
| 146 154 | 
             
                  if !overlap_ids.empty?
         | 
| 147 | 
            -
                    overlap_names = overlap_ids.map {|i| users.by_id(i).all.first.name rescue "#{i}" }
         | 
| 148 | 
            -
                    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(', ')}"
         | 
| 149 157 | 
             
                    success = false
         | 
| 150 158 | 
             
                  end
         | 
| 151 159 |  | 
| 152 160 | 
             
                  # Check that we don't have zombie USAGs left around (not 100% reliable)
         | 
| 153 161 | 
             
                  # because someone could create a group that looks like a USAG
         | 
| 154 162 | 
             
                  possible_usags = org.groups.list(:all) - user_ids
         | 
| 155 | 
            -
                  usags = possible_usags.select {|n| n =~ /^\h+{20}$/ }
         | 
| 163 | 
            +
                  usags = possible_usags.select { |n| n =~ /^\h+{20}$/ }
         | 
| 156 164 | 
             
                  if !usags.empty?
         | 
| 157 | 
            -
                    puts "#{orgname} Suspicious USAGS without associated user #{usags.join(', ') | 
| 165 | 
            +
                    puts "#{orgname} Suspicious USAGS without associated user #{usags.join(', ')}"
         | 
| 158 166 | 
             
                  end
         | 
| 159 167 |  | 
| 160 168 | 
             
                  # Check group membership for sanity
         | 
| 161 | 
            -
                  success &= check_group(org,  | 
| 162 | 
            -
                  success &= check_group(org,  | 
| 169 | 
            +
                  success &= check_group(org, "billing-admins", usernames)
         | 
| 170 | 
            +
                  success &= check_group(org, "admins", usernames)
         | 
| 163 171 |  | 
| 164 172 | 
             
                  # TODO check for non-usags in users!
         | 
| 165 | 
            -
                  users_members = org.groups[ | 
| 166 | 
            -
                  users_actors = users_members[ | 
| 173 | 
            +
                  users_members = org.groups["users"].group
         | 
| 174 | 
            +
                  users_actors = users_members["actors"] - [[:global, "pivotal"]]
         | 
| 167 175 | 
             
                  if !users_actors.empty?
         | 
| 168 176 | 
             
                    puts "#{orgname} has actors in it's users group #{users_actors}"
         | 
| 169 177 | 
             
                  end
         | 
| 170 | 
            -
                  non_usags = users_members[ | 
| 178 | 
            +
                  non_usags = users_members["groups"].map { |g| g[1] } - user_ids
         | 
| 171 179 | 
             
                  if !non_usags.empty?
         | 
| 172 180 | 
             
                    puts "#{orgname} warning: has non usags in it's users group #{non_usags.join(', ')}"
         | 
| 173 181 | 
             
                  end
         | 
| 174 182 |  | 
| 175 | 
            -
             | 
| 176 183 | 
             
                  # Check individual associations
         | 
| 177 184 | 
             
                  users_in_org.each do |user|
         | 
| 178 | 
            -
                    result =  | 
| 179 | 
            -
                    if  | 
| 185 | 
            +
                    result = check_association(org, user, global_admins)
         | 
| 186 | 
            +
                    if result != true
         | 
| 180 187 | 
             
                      puts "Org #{orgname} Association check failed for #{user.name} #{result}"
         | 
| 181 188 | 
             
                      success = false
         | 
| 182 189 | 
             
                    end
         | 
| 183 190 | 
             
                  end
         | 
| 184 191 |  | 
| 185 192 | 
             
                  puts "Org #{orgname} is #{success ? 'ok' : 'bad'} (#{users_in_org.count} users)"
         | 
| 186 | 
            -
                   | 
| 193 | 
            +
                  success
         | 
| 187 194 | 
             
                end
         | 
| 188 195 |  | 
| 189 196 | 
             
                # expect at least one current user to be in admins and billing admins
         | 
| @@ -193,50 +200,40 @@ module ChefFixie | |
| 193 200 | 
             
                    puts "#{orgname} Missing group #{groupname}"
         | 
| 194 201 | 
             
                    return :no_such_group
         | 
| 195 202 | 
             
                  end
         | 
| 196 | 
            -
                  actors = g.group[ | 
| 203 | 
            +
                  actors = g.group["actors"].map { |x| x[1] }
         | 
| 197 204 | 
             
                  live = actors & users
         | 
| 198 205 |  | 
| 199 206 | 
             
                  if live.count == 0
         | 
| 200 207 | 
             
                    puts "Org #{org.name} has no active users in #{groupname}"
         | 
| 201 208 | 
             
                    return false
         | 
| 202 209 | 
             
                  end
         | 
| 203 | 
            -
                   | 
| 210 | 
            +
                  true
         | 
| 204 211 | 
             
                end
         | 
| 205 212 |  | 
| 206 | 
            -
             | 
| 207 | 
            -
                ## TODO: Port this
         | 
| 208 213 | 
             
                def self.remove_association(org, user)
         | 
| 209 214 | 
             
                  # magic to make usage easier
         | 
| 210 | 
            -
                  org =  | 
| 211 | 
            -
                  user =  | 
| 215 | 
            +
                  org = make_org(org)
         | 
| 216 | 
            +
                  user = make_user(user)
         | 
| 212 217 |  | 
| 213 218 | 
             
                  # remove USAG
         | 
| 214 | 
            -
                   | 
| 219 | 
            +
                  usag = org.groups[user.id]
         | 
| 220 | 
            +
                  usag.delete if usag
         | 
| 215 221 |  | 
| 216 | 
            -
                  # remove  | 
| 217 | 
            -
                   | 
| 218 | 
            -
             | 
| 219 | 
            -
                   | 
| 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
         | 
| 220 226 |  | 
| 221 | 
            -
                   | 
| 222 | 
            -
                   | 
| 223 | 
            -
                  OrgMapper::RawAuth.put("actors/#{u_aid}/acl/read", read_ace)
         | 
| 227 | 
            +
                  # remove read ACE
         | 
| 228 | 
            +
                  user.ace_delete(:read, org.global_admins)
         | 
| 224 229 |  | 
| 225 230 | 
             
                  # remove association record
         | 
| 231 | 
            +
                  assoc = assocs.by_org_id_user_id(org.id, user.id)
         | 
| 232 | 
            +
                  assoc.delete if assoc
         | 
| 226 233 |  | 
| 227 | 
            -
                   | 
| 228 | 
            -
                   | 
| 229 | 
            -
             | 
| 230 | 
            -
                  OrgMapper::CouchSupport.delete_account_doc(doc[:id])
         | 
| 231 | 
            -
             | 
| 232 | 
            -
                  # clean up excess invites
         | 
| 233 | 
            -
                  invites = OrgMapper::CouchSupport.invites_for_org(orgname)
         | 
| 234 | 
            -
                  invite_map = invites.inject({}) {|a,e| a[e[:name]] = e; a}
         | 
| 235 | 
            -
             | 
| 236 | 
            -
                  if invite_map.has_key?(username)
         | 
| 237 | 
            -
                    invite = invite_map[username]
         | 
| 238 | 
            -
                    OrgMapper::CouchSupport.delete_account_doc(invite[:id])
         | 
| 239 | 
            -
                  end
         | 
| 234 | 
            +
                  # remove any invites
         | 
| 235 | 
            +
                  invite = invites.by_org_id_user_id(org.id, user.id)
         | 
| 236 | 
            +
                  invite.delete if invite
         | 
| 240 237 | 
             
                end
         | 
| 241 238 | 
             
              end
         | 
| 242 239 | 
             
            end
         | 
    
        data/lib/chef_fixie/config.rb
    CHANGED
    
    | @@ -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  | 
| 22 | 
            -
            require  | 
| 23 | 
            -
            require  | 
| 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) ||  | 
| 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,25 +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 | 
| 105 | 
            +
                  config_files = %w{chef-server-running.json}
         | 
| 105 106 | 
             
                  config = load_json_from_path([configdir], config_files)
         | 
| 106 107 |  | 
| 107 | 
            -
                   | 
| 108 | 
            -
             | 
| 109 | 
            -
                   | 
| 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[ | 
| 113 | 
            -
             | 
| 114 | 
            -
                  sql_config = config[ | 
| 115 | 
            -
                  
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                   | 
| 118 | 
            -
                   | 
| 119 | 
            -
                   | 
| 120 | 
            -
                  
         | 
| 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 | 
            +
             | 
| 121 125 | 
             
                  @sql_database = "postgres://#{sql_user}:#{sql_pw}@#{sql_vip}/opscode_chef"
         | 
| 122 | 
            -
             | 
| 126 | 
            +
             | 
| 123 127 | 
             
                  @pivotal_key = configdir + "pivotal.pem"
         | 
| 124 128 | 
             
                end
         | 
| 125 129 |  | 
| @@ -135,5 +139,36 @@ module ChefFixie | |
| 135 139 | 
             
                    end
         | 
| 136 140 | 
             
                  end
         | 
| 137 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 | 
            +
             | 
| 138 173 | 
             
              end
         | 
| 139 174 | 
             
            end
         |