summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Wrock <matt@mattwrock.com>2016-04-29 19:50:04 -0700
committerMatt Wrock <matt@mattwrock.com>2016-05-04 14:44:38 -0700
commitb1de5700c49920c3ac478ac1061e1af80d463276 (patch)
tree8475742adf379ece05a496a99a131bff5329894e
parentdb27c5675c8367fdf5615e507ddd35fac8420710 (diff)
downloadchef-b1de5700c49920c3ac478ac1061e1af80d463276.tar.gz
adds a system check for fips enablement and runs in fips mode if enabled
-rw-r--r--chef-config/lib/chef-config/config.rb6
-rw-r--r--chef-config/lib/chef-config/fips.rb51
-rw-r--r--chef-config/spec/unit/config_spec.rb40
-rw-r--r--chef-config/spec/unit/fips_spec.rb122
4 files changed, 218 insertions, 1 deletions
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index e6192c22cb..e237f10412 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -22,6 +22,7 @@
require "mixlib/config"
require "pathname"
+require "chef-config/fips"
require "chef-config/logger"
require "chef-config/windows"
require "chef-config/path_helper"
@@ -513,7 +514,9 @@ module ChefConfig
default :recipe_url, nil
# Set to true if Chef is to set OpenSSL to run in FIPS mode
- default(:fips) { ENV["CHEF_FIPS"] == "1" }
+ default(:fips) do
+ !ENV["CHEF_FIPS"].nil? || ChefConfig.fips?
+ end
# Initialize openssl
def self.init_openssl
@@ -966,6 +969,7 @@ module ChefConfig
Digest.const_set("SHA1", OpenSSL::Digest::SHA1)
OpenSSL::Digest.send(:remove_const, "MD5") if OpenSSL::Digest.const_defined?("MD5")
OpenSSL::Digest.const_set("MD5", Digest::MD5)
+ ChefConfig.logger.debug "FIPS mode is enabled."
end
end
end
diff --git a/chef-config/lib/chef-config/fips.rb b/chef-config/lib/chef-config/fips.rb
new file mode 100644
index 0000000000..623ce87686
--- /dev/null
+++ b/chef-config/lib/chef-config/fips.rb
@@ -0,0 +1,51 @@
+#
+# Author:: Matt Wrock (<matt@mattwrock.com>)
+# Copyright:: Copyright (c) 2016 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.
+#
+
+module ChefConfig
+
+ def self.fips?
+ if ChefConfig.windows?
+ begin
+ require "win32/registry"
+ rescue LoadError
+ return false
+ end
+
+ # from http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx
+ reg_type =
+ case ::RbConfig::CONFIG["target_cpu"]
+ when "i386"
+ Win32::Registry::KEY_READ | 0x100
+ when "x86_64"
+ Win32::Registry::KEY_READ | 0x200
+ else
+ Win32::Registry::KEY_READ
+ end
+ begin
+ Win32::Registry::HKEY_LOCAL_MACHINE.open('System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy', reg_type) do |policy|
+ policy["Enabled"] != 0
+ end
+ rescue Win32::Registry::Error
+ false
+ end
+ else
+ fips_path = "/proc/sys/crypto/fips_enabled"
+ File.exist?(fips_path) && File.read(fips_path).chomp != "0"
+ end
+ end
+end
diff --git a/chef-config/spec/unit/config_spec.rb b/chef-config/spec/unit/config_spec.rb
index 72c0981eca..f09dbb517a 100644
--- a/chef-config/spec/unit/config_spec.rb
+++ b/chef-config/spec/unit/config_spec.rb
@@ -165,6 +165,46 @@ RSpec.describe ChefConfig::Config do
allow(ChefConfig::Config).to receive(:path_accessible?).and_return(false)
end
+ describe "ChefConfig::Config[:fips]" do
+ let(:fips_enabled) { false }
+
+ before(:all) do
+ @original_env = ENV.to_hash
+ end
+
+ after(:all) do
+ ENV.clear
+ ENV.update(@original_env)
+ end
+
+ before(:each) do
+ ENV["CHEF_FIPS"] = nil
+ allow(ChefConfig).to receive(:fips?).and_return(fips_enabled)
+ end
+
+ it "returns false when no environment is set and not enabled on system" do
+ expect(ChefConfig::Config[:fips]).to eq(false)
+ end
+
+ context "when ENV['CHEF_FIPS'] is set" do
+ before do
+ ENV["CHEF_FIPS"] = "1"
+ end
+
+ it "returns true" do
+ expect(ChefConfig::Config[:fips]).to eq(true)
+ end
+ end
+
+ context "when fips is enabled on system" do
+ let(:fips_enabled) { true }
+
+ it "returns true" do
+ expect(ChefConfig::Config[:fips]).to eq(true)
+ end
+ end
+ end
+
describe "ChefConfig::Config[:chef_server_root]" do
context "when chef_server_url isn't set manually" do
it "returns the default of 'https://localhost:443'" do
diff --git a/chef-config/spec/unit/fips_spec.rb b/chef-config/spec/unit/fips_spec.rb
new file mode 100644
index 0000000000..cf5af22ef1
--- /dev/null
+++ b/chef-config/spec/unit/fips_spec.rb
@@ -0,0 +1,122 @@
+#
+# Author:: Matt Wrock (<matt@mattwrock.com>)
+# Copyright:: Copyright (c) 2016 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 "chef-config/fips"
+require "spec_helper"
+
+RSpec.describe "ChefConfig.fips?" do
+ let(:enabled) { "0" }
+
+ context "on *nix" do
+ let(:fips_path) { "/proc/sys/crypto/fips_enabled" }
+
+ before(:each) do
+ allow(ChefConfig).to receive(:windows?).and_return(false)
+ allow(::File).to receive(:exist?).with(fips_path).and_return(true)
+ allow(::File).to receive(:read).with(fips_path).and_return(enabled)
+ end
+
+ context "fips file is present and contains 1" do
+ let(:enabled) { "1" }
+
+ it "returns true" do
+ expect(ChefConfig.fips?).to be(true)
+ end
+ end
+
+ context "fips file does not contain 1" do
+ let(:enabled) { "0" }
+
+ it "returns false" do
+ expect(ChefConfig.fips?).to be(false)
+ end
+ end
+
+ context "fips file is not present" do
+ before do
+ allow(::File).to receive(:exist?).with(fips_path).and_return(false)
+ end
+
+ it "returns false" do
+ expect(ChefConfig.fips?).to be(false)
+ end
+ end
+ end
+
+ context "on windows", :windows_only do
+ let(:fips_key) { 'System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy' }
+ let(:win_reg_entry) { { "Enabled" => enabled } }
+
+ before(:each) do
+ allow(ChefConfig).to receive(:windows?).and_return(true)
+ allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with(fips_key, arch).and_yield(win_reg_entry)
+ end
+
+ shared_examples "fips_detection" do
+ context "fips enabled key is set to 1" do
+ let(:enabled) { 1 }
+
+ it "returns true" do
+ expect(ChefConfig.fips?).to be(true)
+ end
+ end
+
+ context "fips enabled key is set to 0" do
+ let(:enabled) { 0 }
+
+ it "returns false" do
+ expect(ChefConfig.fips?).to be(false)
+ end
+ end
+
+ context "fips key does not exist" do
+ before do
+ allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).and_raise(Win32::Registry::Error, 50)
+ end
+
+ it "returns false" do
+ expect(ChefConfig.fips?).to be(false)
+ end
+ end
+ end
+
+ context "on 32 bit ruby" do
+ let(:arch) { Win32::Registry::KEY_READ | 0x100 }
+
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "i386" } ) }
+
+ it_behaves_like "fips_detection"
+ end
+
+ context "on 64 bit ruby" do
+ let(:arch) { Win32::Registry::KEY_READ | 0x200 }
+
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => "x86_64" } ) }
+
+ it_behaves_like "fips_detection"
+ end
+
+ context "on unknown ruby" do
+ let(:arch) { Win32::Registry::KEY_READ }
+
+ before { stub_const("::RbConfig::CONFIG", { "target_cpu" => nil } ) }
+
+ it_behaves_like "fips_detection"
+ end
+ end
+end