summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom May <thom@may.lt>2017-12-18 18:31:58 +0000
committerGitHub <noreply@github.com>2017-12-18 18:31:58 +0000
commit925051d67b36a2b6c6a13c99cccf4109e99987f5 (patch)
tree087260689310c208d67eed36cab4e7cd62e9f5fd
parenteccc48d63e3bc99d161ad6ca48f7770fcd2b9b59 (diff)
parent92671398a99bb4393650f4343c3b2a20814eb3eb (diff)
downloadchef-925051d67b36a2b6c6a13c99cccf4109e99987f5.tar.gz
Merge pull request #6660 from chef/tm/credentials
implement credential management
-rw-r--r--Gemfile.lock1
-rw-r--r--chef-config/chef-config.gemspec1
-rw-r--r--chef-config/lib/chef-config/config.rb10
-rw-r--r--chef-config/lib/chef-config/mixin/credentials.rb57
-rw-r--r--chef-config/lib/chef-config/workstation_config_loader.rb44
-rw-r--r--chef-config/spec/unit/workstation_config_loader_spec.rb144
-rw-r--r--lib/chef/application/knife.rb4
-rw-r--r--lib/chef/knife.rb5
-rw-r--r--lib/chef/knife/configure.rb48
-rw-r--r--lib/chef/server_api.rb1
-rw-r--r--spec/unit/knife/configure_spec.rb70
-rw-r--r--spec/unit/knife_spec.rb2
12 files changed, 287 insertions, 100 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 401a1f95f0..e9881a050f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -97,6 +97,7 @@ PATH
fuzzyurl
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
+ tomlrb (~> 1.2)
GEM
remote: https://rubygems.org/
diff --git a/chef-config/chef-config.gemspec b/chef-config/chef-config.gemspec
index 9e40528fba..1dc1a118ff 100644
--- a/chef-config/chef-config.gemspec
+++ b/chef-config/chef-config.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "mixlib-config", "~> 2.0"
spec.add_dependency "fuzzyurl"
spec.add_dependency "addressable"
+ spec.add_dependency "tomlrb", "~> 1.2"
spec.add_development_dependency "rake", "~> 10.0"
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index beb78f25d0..4855533266 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -592,6 +592,12 @@ module ChefConfig
# If chef-zero is enabled, this defaults to nil (no authentication).
default(:client_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/client.pem") }
+ # A credentials file may contain a complete client key, rather than the path
+ # to one.
+ #
+ # We'll use this preferentially.
+ default :client_key_contents, nil
+
# When registering the client, should we allow the client key location to
# be a symlink? eg: /etc/chef/client.pem -> /etc/chef/prod-client.pem
# If the path of the key goes through a directory like /tmp this should
@@ -631,6 +637,7 @@ module ChefConfig
default(:validation_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/validation.pem") }
default :validation_client_name, "chef-validator"
+ default :validation_key_contents, nil
# When creating a new client via the validation_client account, Chef 11
# servers allow the client to generate a key pair locally and send the
# public key to the server. This is more secure and helps offload work from
@@ -691,6 +698,9 @@ module ChefConfig
# on running chef-client
default :count_log_resource_updates, true
+ # The selected profile when using credentials.
+ default :profile, nil
+
# knife configuration data
config_context :knife do
# XXX: none of these default values are applied to knife (and would create a backcompat
diff --git a/chef-config/lib/chef-config/mixin/credentials.rb b/chef-config/lib/chef-config/mixin/credentials.rb
new file mode 100644
index 0000000000..4c0192fff8
--- /dev/null
+++ b/chef-config/lib/chef-config/mixin/credentials.rb
@@ -0,0 +1,57 @@
+#
+# Copyright:: Copyright 2017, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "tomlrb"
+require "chef-config/path_helper"
+
+module ChefConfig
+ module Mixin
+ module Credentials
+
+ def load_credentials(profile = nil)
+ credentials_file = PathHelper.home(".chef", "credentials").freeze
+ context_file = PathHelper.home(".chef", "context").freeze
+
+ return unless File.file?(credentials_file)
+
+ context = File.read(context_file) if File.file?(context_file)
+
+ environment = ENV.fetch("CHEF_PROFILE", nil)
+
+ profile = if !profile.nil?
+ profile
+ elsif !environment.nil?
+ environment
+ elsif !context.nil?
+ context
+ else
+ "default"
+ end
+
+ config = Tomlrb.load_file(credentials_file)
+ apply_credentials(config[profile], profile)
+ rescue ChefConfig::ConfigurationError
+ raise
+ rescue => e
+ # TOML's error messages are mostly rubbish, so we'll just give a generic one
+ message = "Unable to parse Credentials file: #{credentials_file}\n"
+ message << e.message
+ raise ChefConfig::ConfigurationError, message
+ end
+ end
+ end
+end
diff --git a/chef-config/lib/chef-config/workstation_config_loader.rb b/chef-config/lib/chef-config/workstation_config_loader.rb
index babb78aeb8..2738d6a1a2 100644
--- a/chef-config/lib/chef-config/workstation_config_loader.rb
+++ b/chef-config/lib/chef-config/workstation_config_loader.rb
@@ -22,24 +22,31 @@ require "chef-config/logger"
require "chef-config/path_helper"
require "chef-config/windows"
require "chef-config/mixin/dot_d"
+require "chef-config/mixin/credentials"
module ChefConfig
class WorkstationConfigLoader
include ChefConfig::Mixin::DotD
+ include ChefConfig::Mixin::Credentials
# Path to a config file requested by user, (e.g., via command line option). Can be nil
attr_accessor :explicit_config_file
+ # The name of a credentials profile. Can be nil
+ attr_accessor :profile
+ attr_reader :credentials_found
# TODO: initialize this with a logger for Chef and Knife
- def initialize(explicit_config_file, logger = nil)
+ def initialize(explicit_config_file, logger = nil, profile: nil)
@explicit_config_file = explicit_config_file
@chef_config_dir = nil
@config_location = nil
+ @profile = profile
@logger = logger || NullLogger.new
+ @credentials_found = false
end
def no_config_found?
- config_location.nil?
+ config_location.nil? && !credentials_found
end
def config_location
@@ -62,6 +69,7 @@ module ChefConfig
end
def load
+ load_credentials(profile)
# Ignore it if there's no explicit_config_file and can't find one at a
# default path.
if !config_location.nil?
@@ -138,6 +146,38 @@ module ChefConfig
a
end
+ def apply_credentials(creds, profile)
+ Config.profile ||= profile
+ if creds.key?("node_name") && creds.key?("client_name")
+ raise ChefConfig::ConfigurationError, "Do not specify both node_name and client_name. You should prefer client_name."
+ end
+ Config.node_name = creds.fetch("node_name") if creds.key?("node_name")
+ Config.node_name = creds.fetch("client_name") if creds.key?("client_name")
+ Config.chef_server_url = creds.fetch("chef_server_url") if creds.key?("chef_server_url")
+ Config.validation_client_name = creds.fetch("validation_client_name") if creds.key?("validation_client_name")
+
+ extract_key(creds, "validation_key", :validation_key, :validation_key_contents)
+ extract_key(creds, "validator_key", :validation_key, :validation_key_contents)
+ extract_key(creds, "client_key", :client_key, :client_key_contents)
+ @credentials_found = true
+ end
+
+ def extract_key(creds, name, config_path, config_contents)
+ return unless creds.has_key?(name)
+
+ val = creds.fetch(name)
+ if val.start_with?("-----BEGIN RSA PRIVATE KEY-----")
+ Config.send(config_contents, val)
+ else
+ abs_path = Pathname.new(val).expand_path(home_chef_dir)
+ Config.send(config_path, abs_path)
+ end
+ end
+
+ def home_chef_dir
+ @home_chef_dir ||= PathHelper.home(".chef")
+ end
+
def apply_config(config_content, config_file_path)
Config.from_string(config_content, config_file_path)
rescue SignalException
diff --git a/chef-config/spec/unit/workstation_config_loader_spec.rb b/chef-config/spec/unit/workstation_config_loader_spec.rb
index 087f249724..509d95fe36 100644
--- a/chef-config/spec/unit/workstation_config_loader_spec.rb
+++ b/chef-config/spec/unit/workstation_config_loader_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do
before do
# We set this to nil so that a dev workstation will
# not interfere with the tests.
+ ChefConfig::Config.reset
ChefConfig::Config[:config_d_dir] = nil
end
@@ -363,4 +364,147 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do
end
end
end
+
+ describe "when loading a credentials file" do
+ if ChefConfig.windows?
+ let(:home) { "C:/Users/example.user" }
+ else
+ let(:home) { "/Users/example.user" }
+ end
+ let(:credentials_file) { "#{home}/.chef/credentials" }
+ let(:context_file) { "#{home}/.chef/context" }
+
+ before do
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_return(File.join(home, ".chef"))
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "credentials").and_return(credentials_file)
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "context").and_return(context_file)
+ allow(File).to receive(:file?).with(context_file).and_return false
+ end
+
+ context "when the file exists" do
+ before do
+ expect(File).to receive(:read).with(credentials_file, { encoding: "utf-8" }).and_return(content)
+ allow(File).to receive(:file?).with(credentials_file).and_return true
+ end
+
+ context "and has a default profile" do
+ let(:content) do
+ content = <<EOH
+[default]
+node_name = 'barney'
+client_key = "barney_rubble.pem"
+chef_server_url = "https://api.chef.io/organizations/bedrock"
+EOH
+ content
+ end
+
+ it "applies the expected config" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.chef_server_url).to eq("https://api.chef.io/organizations/bedrock")
+ expect(ChefConfig::Config.client_key.to_s).to eq("#{home}/.chef/barney_rubble.pem")
+ expect(ChefConfig::Config.profile.to_s).to eq("default")
+ end
+ end
+
+ context "and has a profile containing a full key" do
+ let(:content) do
+ content = <<EOH
+[default]
+client_key = """
+-----BEGIN RSA PRIVATE KEY-----
+foo
+"""
+EOH
+ content
+ end
+
+ it "applies the expected config" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.client_key_contents).to eq(<<EOH
+-----BEGIN RSA PRIVATE KEY-----
+foo
+EOH
+)
+ end
+ end
+
+ context "and has several profiles" do
+ let(:content) do
+ content = <<EOH
+[default]
+client_name = "default"
+[environment]
+client_name = "environment"
+[explicit]
+client_name = "explicit"
+[context]
+client_name = "context"
+EOH
+ content
+ end
+
+ let(:env) { {} }
+ before do
+ stub_const("ENV", env)
+ end
+
+ it "selects the correct profile explicitly" do
+ expect { config_loader.load_credentials("explicit") }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("explicit")
+ end
+
+ context "with an environment variable" do
+ let(:env) { { "CHEF_PROFILE" => "environment" } }
+
+ it "selects the correct profile" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("environment")
+ end
+ end
+
+ it "selects the correct profile with a context file" do
+ allow(File).to receive(:file?).with(context_file).and_return true
+ expect(File).to receive(:read).with(context_file).and_return "context"
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("context")
+ end
+
+ it "falls back to the default" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("default")
+ end
+ end
+
+ context "and contains both node_name and client_name" do
+ let(:content) do
+ content = <<EOH
+[default]
+node_name = 'barney'
+client_name = 'barney'
+EOH
+ content
+ end
+
+ it "raises a ConfigurationError" do
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
+ end
+ end
+
+ context "and has a syntax error" do
+ let(:content) { "<<<<<" }
+
+ it "raises a ConfigurationError" do
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
+ end
+ end
+ end
+
+ context "when the file does not exist" do
+ it "does not load anything" do
+ allow(File).to receive(:file?).with(credentials_file).and_return false
+ expect(Tomlrb).not_to receive(:load_file)
+ config_loader.load_credentials
+ end
+ end
+ end
end
diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb
index 6a09427ccd..c972e9313e 100644
--- a/lib/chef/application/knife.rb
+++ b/lib/chef/application/knife.rb
@@ -148,6 +148,10 @@ class Chef::Application::Knife < Chef::Application
:boolean => true,
:default => nil
+ option :profile,
+ :long => "--profile PROFILE",
+ :description => "The credentials profile to select"
+
# Run knife
def run
Mixlib::Log::Formatter.show_time = false
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 65d687af70..663649f32f 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -177,8 +177,9 @@ class Chef
@config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
end
- def self.load_config(explicit_config_file)
+ def self.load_config(explicit_config_file, profile)
config_loader.explicit_config_file = explicit_config_file
+ config_loader.profile = profile
config_loader.load
ui.warn("No knife configuration file found") if config_loader.no_config_found?
@@ -404,7 +405,7 @@ class Chef
def configure_chef
# knife needs to send logger output to STDERR by default
Chef::Config[:log_location] = STDERR
- config_loader = self.class.load_config(config[:config_file])
+ config_loader = self.class.load_config(config[:config_file], config[:profile])
config[:config_file] = config_loader.config_location
# For CLI options like `--config-option key=value`. These have to get
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index 967a18de87..10ae62b6c9 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -17,6 +17,7 @@
#
require "chef/knife"
+require "chef/util/path_helper"
class Chef
class Knife
@@ -67,24 +68,22 @@ class Chef
end
def run
- ask_user_for_config_path
-
FileUtils.mkdir_p(chef_config_path)
+ config_file = File.join(chef_config_path, "credentials")
ask_user_for_config
- ::File.open(config[:config_file], "w") do |f|
+ config_file = File.expand_path(config_file)
+ if File.exist?(config_file)
+ confirm("Overwrite #{config_file}?")
+ end
+ ::File.open(config_file, "w") do |f|
f.puts <<-EOH
-node_name '#{new_client_name}'
-client_key '#{new_client_key}'
-validation_client_name '#{validation_client_name}'
-validation_key '#{validation_key}'
-chef_server_url '#{chef_server}'
-syntax_check_cache_path '#{File.join(chef_config_path, "syntax_check_cache")}'
+[default]
+client_name = '#{new_client_name}'
+client_key = '#{new_client_key}'
+chef_server_url = '#{chef_server}'
EOH
- unless chef_repo.empty?
- f.puts "cookbook_path [ '#{chef_repo}/cookbooks' ]"
- end
end
if config[:initial]
@@ -109,26 +108,11 @@ EOH
ui.msg("Before running commands with Knife")
ui.msg("")
ui.msg("*****")
- ui.msg("")
- ui.msg("You must place your validation key in:")
- ui.msg(" #{validation_key}")
- ui.msg("Before generating instance data with Knife")
- ui.msg("")
- ui.msg("*****")
end
ui.msg("Configuration file written to #{config[:config_file]}")
end
- def ask_user_for_config_path
- config[:config_file] ||= ask_question("Where should I put the config file? ", :default => "#{Chef::Config[:user_home]}/.chef/knife.rb")
- # have to use expand path to expand the tilde character to the user's home
- config[:config_file] = File.expand_path(config[:config_file])
- if File.exists?(config[:config_file])
- confirm("Overwrite #{config[:config_file]}")
- end
- end
-
def ask_user_for_config
server_name = guess_servername
@chef_server = config[:chef_server_url] || ask_question("Please enter the chef server URL: ", :default => "https://#{server_name}/organizations/myorg")
@@ -140,10 +124,6 @@ EOH
else
@new_client_name = config[:node_name] || ask_question("Please enter an existing username or clientname for the API: ", :default => Etc.getlogin)
end
- @validation_client_name = config[:validation_client_name] || ask_question("Please enter the validation clientname: ", :default => "chef-validator")
- @validation_key = config[:validation_key] || ask_question("Please enter the location of the validation key: ", :default => "/etc/chef-server/chef-validator.pem")
- @validation_key = File.expand_path(@validation_key)
- @chef_repo = config[:repository] || ask_question("Please enter the path to a chef repository (or leave blank): ")
@new_client_key = config[:client_key] || File.join(chef_config_path, "#{@new_client_name}.pem")
@new_client_key = File.expand_path(@new_client_key)
@@ -157,12 +137,8 @@ EOH
o[:fqdn] || o[:machinename] || o[:hostname] || "localhost"
end
- def config_file
- config[:config_file]
- end
-
def chef_config_path
- File.dirname(config_file)
+ Chef::Util::PathHelper.home(".chef")
end
end
end
diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb
index 2bdc5d9fe8..c501544954 100644
--- a/lib/chef/server_api.rb
+++ b/lib/chef/server_api.rb
@@ -31,6 +31,7 @@ class Chef
def initialize(url = Chef::Config[:chef_server_url], options = {})
options[:client_name] ||= Chef::Config[:node_name]
+ options[:raw_key] ||= Chef::Config[:client_key_contents]
options[:signing_key_filename] ||= Chef::Config[:client_key] unless options[:raw_key]
options[:signing_key_filename] = nil if chef_zero_uri?(url)
options[:inflate_json_class] = false
diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb
index b7802d3890..f1d3bd0745 100644
--- a/spec/unit/knife/configure_spec.rb
+++ b/spec/unit/knife/configure_spec.rb
@@ -124,55 +124,12 @@ describe Chef::Knife::Configure do
end
end
- it "asks the user for the location of a chef repo" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the path to a chef repository (or leave blank):"))
- expect(@knife.chef_repo).to eq("")
- end
-
- it "asks the users for the name of the validation client" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the validation clientname: [chef-validator]"))
- expect(@knife.validation_client_name).to eq("chef-validator")
- end
-
- it "should not ask the users for the name of the validation client if --validation_client_name is specified" do
- @knife.config[:validation_client_name] = "my-validator"
- @knife.ask_user_for_config
- expect(@out.string).not_to match(Regexp.escape("Please enter the validation clientname:"))
- expect(@knife.validation_client_name).to eq("my-validator")
- end
-
- it "asks the users for the location of the validation key" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the location of the validation key: [#{default_validator_key}]"))
- if windows?
- expect(@knife.validation_key.capitalize).to eq(default_validator_key_win32.capitalize)
- else
- expect(@knife.validation_key).to eq(default_validator_key)
- end
- end
-
- it "should not ask the users for the location of the validation key if --validation_key is specified" do
- @knife.config[:validation_key] = "/home/you/.chef/my-validation.pem"
- @knife.ask_user_for_config
- expect(@out.string).not_to match(Regexp.escape("Please enter the location of the validation key:"))
- if windows?
- expect(@knife.validation_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-validation\.pem$}
- else
- expect(@knife.validation_key).to eq("/home/you/.chef/my-validation.pem")
- end
- end
-
it "should not ask the user for anything if -i and all other properties are specified" do
@knife.config[:initial] = true
@knife.config[:chef_server_url] = "http://localhost:5000"
@knife.config[:node_name] = "testnode"
@knife.config[:admin_client_name] = "my-webui"
@knife.config[:admin_client_key] = "/home/you/.chef/my-webui.pem"
- @knife.config[:validation_client_name] = "my-validator"
- @knife.config[:validation_key] = "/home/you/.chef/my-validation.pem"
- @knife.config[:repository] = ""
@knife.config[:client_key] = "/home/you/a-new-user.pem"
allow(Etc).to receive(:getlogin).and_return("a-new-user")
@@ -184,40 +141,33 @@ describe Chef::Knife::Configure do
expect(@knife.admin_client_name).to eq("my-webui")
if windows?
expect(@knife.admin_client_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-webui\.pem$}
- expect(@knife.validation_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-validation\.pem$}
expect(@knife.new_client_key).to match %r{^[A-Za-z]:/home/you/a-new-user\.pem$}
else
expect(@knife.admin_client_key).to eq("/home/you/.chef/my-webui.pem")
- expect(@knife.validation_key).to eq("/home/you/.chef/my-validation.pem")
expect(@knife.new_client_key).to eq("/home/you/a-new-user.pem")
end
- expect(@knife.validation_client_name).to eq("my-validator")
- expect(@knife.chef_repo).to eq("")
end
it "writes the new data to a config file" do
- allow(File).to receive(:expand_path).with("/home/you/.chef/knife.rb").and_return("/home/you/.chef/knife.rb")
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef")
+ allow(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials")
allow(File).to receive(:expand_path).with("/home/you/.chef/#{Etc.getlogin}.pem").and_return("/home/you/.chef/#{Etc.getlogin}.pem")
- allow(File).to receive(:expand_path).with(default_validator_key).and_return(default_validator_key)
allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef")
config_file = StringIO.new
- expect(::File).to receive(:open).with("/home/you/.chef/knife.rb", "w").and_yield config_file
+ expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w").and_yield config_file
@knife.config[:repository] = "/home/you/chef-repo"
@knife.run
- expect(config_file.string).to match(/^node_name[\s]+'#{Etc.getlogin}'$/)
- expect(config_file.string).to match(%r{^client_key[\s]+'/home/you/.chef/#{Etc.getlogin}.pem'$})
- expect(config_file.string).to match(/^validation_client_name\s+'chef-validator'$/)
- expect(config_file.string).to match(%r{^validation_key\s+'#{default_validator_key}'$})
- expect(config_file.string).to match(%r{^chef_server_url\s+'#{default_server_url}'$})
- expect(config_file.string).to match(%r{cookbook_path\s+\[ '/home/you/chef-repo/cookbooks' \]})
+ expect(config_file.string).to match(/^client_name[\s]+=[\s]+'#{Etc.getlogin}'$/)
+ expect(config_file.string).to match(%r{^client_key[\s]+=[\s]+'/home/you/.chef/#{Etc.getlogin}.pem'$})
+ expect(config_file.string).to match(%r{^chef_server_url\s+=[\s]+'#{default_server_url}'$})
end
it "creates a new client when given the --initial option" do
- expect(File).to receive(:expand_path).with("/home/you/.chef/knife.rb").and_return("/home/you/.chef/knife.rb")
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef")
+ expect(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials")
expect(File).to receive(:expand_path).with("/home/you/.chef/a-new-user.pem").and_return("/home/you/.chef/a-new-user.pem")
- expect(File).to receive(:expand_path).with(default_validator_key).and_return(default_validator_key)
- expect(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
+ allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
Chef::Config[:node_name] = "webmonkey.example.com"
user_command = Chef::Knife::UserCreate.new
@@ -227,7 +177,7 @@ describe Chef::Knife::Configure do
allow(Chef::Knife::UserCreate).to receive(:new).and_return(user_command)
expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef")
- expect(::File).to receive(:open).with("/home/you/.chef/knife.rb", "w")
+ expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w")
@knife.config[:initial] = true
@knife.config[:user_password] = "blah"
@knife.run
diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb
index 2b22dbc4f7..adaab11d55 100644
--- a/spec/unit/knife_spec.rb
+++ b/spec/unit/knife_spec.rb
@@ -47,6 +47,7 @@ describe Chef::Knife do
allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
allow(config_loader).to receive(:explicit_config_file=)
+ allow(config_loader).to receive(:profile=)
# Prevent gratuitous code reloading:
allow(Chef::Knife).to receive(:load_commands)
@@ -331,6 +332,7 @@ describe Chef::Knife do
knife.config[:config_file] = fake_config
config_loader = double("Chef::WorkstationConfigLoader", :load => true, :no_config_found? => false, :chef_config_dir => "/etc/chef", :config_location => fake_config)
allow(config_loader).to receive(:explicit_config_file=).with(fake_config).and_return(fake_config)
+ allow(config_loader).to receive(:profile=)
allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
end