diff options
author | John Keiser <jkeiser@opscode.com> | 2013-10-15 20:41:52 -0700 |
---|---|---|
committer | John Keiser <jkeiser@opscode.com> | 2013-10-15 20:41:52 -0700 |
commit | e1c6bef68597f5c4f418107ef9e3638e44cc8cf7 (patch) | |
tree | c6871e3dcded48265f2b82c26ab13cd62a0ba2be /lib/chef | |
parent | 2da5abd0648f3ba6977d3a69d858078237bee585 (diff) | |
download | chef-e1c6bef68597f5c4f418107ef9e3638e44cc8cf7.tar.gz |
Add --config-file-jail to avoid loading user knife.rb in tests
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/application.rb | 51 | ||||
-rw-r--r-- | lib/chef/application/client.rb | 5 | ||||
-rw-r--r-- | lib/chef/chef_fs/config.rb | 10 | ||||
-rw-r--r-- | lib/chef/chef_fs/path_utils.rb | 5 | ||||
-rw-r--r-- | lib/chef/config.rb | 9 | ||||
-rw-r--r-- | lib/chef/knife.rb | 12 |
6 files changed, 75 insertions, 17 deletions
diff --git a/lib/chef/application.rb b/lib/chef/application.rb index ca9cfff291..2987f58839 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -25,6 +25,8 @@ require 'chef/platform' require 'mixlib/cli' require 'tmpdir' require 'rbconfig' +require 'pathname' +require 'chef/chef_fs/path_utils' class Chef::Application include Mixlib::CLI @@ -75,7 +77,21 @@ class Chef::Application # Parse the config file def load_config_file if !config[:config_file] - Chef::Log.warn("No config file found or specified on command line, not loading.") + Chef::Log.warn("No config file found or specified on command line, using command line options.") + Chef::Config.merge!(config) + return + end + + if !Chef::Application.config_file_exists?(config[:config_file]) + Chef::Log.warn("*****************************************") + if !File.exists?(config[:config_file]) + Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") + else + Chef::Log.warn("Config file #{config[:config_file]} not inside the jail #{Chef::Config.config_file_jail}, using command line options.", 2) + end + Chef::Log.warn("*****************************************") + + Chef::Config.merge!(config) return end @@ -86,12 +102,6 @@ class Chef::Application else ::File::open(config[:config_file]) { |f| apply_config(f.path) } end - rescue Errno::ENOENT => error - Chef::Log.warn("*****************************************") - Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") - Chef::Log.warn("*****************************************") - - Chef::Config.merge!(config) rescue SocketError => error Chef::Application.fatal!("Error getting config file #{config[:config_file]}", 2) rescue Chef::Exceptions::ConfigurationError => error @@ -101,6 +111,33 @@ class Chef::Application end end + # Determines whether a config file exists, taking into account file existence + # as well as Chef::Config.config_file_jail (if they are not under the jail, + # this method will return false). Takes symlinks and relative paths into + # account. + def self.config_file_exists?(config_file) + if config_file =~ /^(http|https):\/\// + return true + end + + begin + real_config_file = Pathname.new(config_file).realpath.to_s + rescue Errno::ENOENT + return false + end + + return true if !Chef::Config.config_file_jail + + begin + jail = Pathname.new(Chef::Config.config_file_jail).realpath.to_s + rescue Errno::ENOENT + Chef::Log.warn("Config file jail #{Chef::Config.config_file_jail} does not exist: will not load any config file.") + return false + end + + Chef::ChefFS::PathUtils.descendant_of?(real_config_file, jail) + end + # Initialize and configure the logger. # === Loggers and Formatters # In Chef 10.x and previous, the Logger was the primary/only way that Chef diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index ea8d599b4c..0964101fad 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -206,6 +206,10 @@ class Chef::Application::Client < Chef::Application :long => "--chef-zero-port PORT", :description => "Port to start chef-zero on" + option :config_file_jail, + :long => "--config-file-jail PATH", + :description => "Directory under which config files are allowed to be loaded (no client.rb or knife.rb outside this path will be loaded)." + if Chef::Platform.windows? option :fatal_windows_admin_check, :short => "-A", @@ -272,6 +276,7 @@ class Chef::Application::Client < Chef::Application end def load_config_file + Chef::Config.config_file_jail = config[:config_file_jail] if config[:config_file_jail] if !config.has_key?(:config_file) if config[:local_mode] require 'chef/knife' diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb index bfbe379775..e08b976961 100644 --- a/lib/chef/chef_fs/config.rb +++ b/lib/chef/chef_fs/config.rb @@ -84,16 +84,14 @@ class Chef # If the path does not reach into ANY specified directory, nil is returned. def server_path(file_path) pwd = File.expand_path(Dir.pwd) - absolute_path = Chef::ChefFS::PathUtils.realest_path(File.expand_path(file_path, pwd)) + absolute_pwd = Chef::ChefFS::PathUtils.realest_path(File.expand_path(file_path, pwd)) # Check all object paths (cookbooks_dir, data_bags_dir, etc.) object_paths.each_pair do |name, paths| paths.each do |path| realest_path = Chef::ChefFS::PathUtils.realest_path(path) - if absolute_path[0,realest_path.length] == realest_path && - (absolute_path.length == realest_path.length || - absolute_path[realest_path.length,1] =~ /#{PathUtils.regexp_path_separator}/) - relative_path = Chef::ChefFS::PathUtils::relative_to(absolute_path, realest_path) + if PathUtils.descendant_of?(absolute_pwd, realest_path) + relative_path = Chef::ChefFS::PathUtils::relative_to(absolute_pwd, realest_path) return relative_path == '.' ? "/#{name}" : "/#{name}/#{relative_path}" end end @@ -102,7 +100,7 @@ class Chef # Check chef_repo_path Array(@chef_config[:chef_repo_path]).flatten.each do |chef_repo_path| realest_chef_repo_path = Chef::ChefFS::PathUtils.realest_path(chef_repo_path) - if absolute_path == realest_chef_repo_path + if absolute_pwd == realest_chef_repo_path return '/' end end diff --git a/lib/chef/chef_fs/path_utils.rb b/lib/chef/chef_fs/path_utils.rb index 805b092b3a..9ef75ce2e5 100644 --- a/lib/chef/chef_fs/path_utils.rb +++ b/lib/chef/chef_fs/path_utils.rb @@ -82,6 +82,11 @@ class Chef end end + def self.descendant_of?(path, ancestor) + path[0,ancestor.length] == ancestor && + (ancestor.length == path.length || path[ancestor.length,1] =~ /#{PathUtils.regexp_path_separator}/) + end + def self.is_absolute?(path) path =~ /^#{regexp_path_separator}/ end diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 0a4ee6e94c..f2610f01e2 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -73,6 +73,13 @@ class Chef formatters << [name, file_path] end + # Config file to load (client.rb, knife.rb, etc. defaults set differently in knife, chef-client, etc.) + configurable(:config_file) + + # No config file (client.rb / knife.rb / etc.) will be loaded outside this path. + # Major use case is tests, where we don't want to load the user's config files. + configurable(:config_file_jail) + default :formatters, [] # Override the config dispatch to set the value of multiple server options simultaneously @@ -215,6 +222,8 @@ class Chef # An array of paths to search for knife exec scripts if they aren't in the current directory default :script_path, [] + # The root of all caches (checksums, cache and backup). If local mode is on, + # this is under the user's home directory. default(:cache_path) do if local_mode "#{user_home}#{platform_path_separator}.chef#{platform_path_separator}local-mode-cache" diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index 5ff6b92643..dbb719c30a 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -335,8 +335,7 @@ class Chef end candidate_configs.each do | candidate_config | - candidate_config = File.expand_path(candidate_config) - if File.exist?(candidate_config) + if Chef::Application.config_file_exists?(candidate_config) return candidate_config end end @@ -403,12 +402,17 @@ class Chef end def configure_chef - unless config[:config_file] + if config[:config_file] + if !Chef::Application.config_file_exists?(config[:config_file]) + ui.error("Specified config file #{config[:config_file]} does not exist#{Chef::Config.config_file_jail ? " or is not under config file jail #{Chef::Config.config_file_jail}" : ""}!") + exit 1 + end + else located_config_file = self.class.locate_config_file config[:config_file] = located_config_file if located_config_file end - # Don't try to load a knife.rb if it doesn't exist. + # Don't try to load a knife.rb if it wasn't specified. if config[:config_file] Chef::Log.debug("Using configuration from #{config[:config_file]}") read_config_file(config[:config_file]) |