diff --git a/logstash-core/build.gradle b/logstash-core/build.gradle index 831f0fefde5..2c3489aadd9 100644 --- a/logstash-core/build.gradle +++ b/logstash-core/build.gradle @@ -220,6 +220,10 @@ idea { } dependencies { + runtimeOnly("org.bouncycastle:bc-fips:2.0.0") + runtimeOnly("org.bouncycastle:bcpkix-fips:2.0.7") + runtimeOnly("org.bouncycastle:bctls-fips:2.0.19") + runtimeOnly("org.bouncycastle:bcutil-fips:2.0.3") api(files("../vendor/jruby/lib/jruby.jar") { // jruby-core.jar builtBy ':downloadAndInstallJRuby' }) { because "DEPENDENCY: org.jruby:jruby-core:${jrubyVersion}" } // meta-data for generateLicenseReport diff --git a/x-pack/lib/fips_validation/extension.rb b/x-pack/lib/fips_validation/extension.rb new file mode 100644 index 00000000000..d8c05e2e049 --- /dev/null +++ b/x-pack/lib/fips_validation/extension.rb @@ -0,0 +1,62 @@ + +require "logstash/environment" + +require "logstash/plugins/registry" + +module LogStash + module FipsValidation + class Extension < LogStash::UniversalPlugin + + LogStash::PLUGIN_REGISTRY.add(:universal, "fips_validation", self) + + include LogStash::Util::Loggable + + def register_hooks(hooks) + require 'logstash/runner' + hooks.register_hooks(LogStash::Runner, self) + end + + def before_bootstrap_checks(runner) + return unless ENV['ENFORCE_FIPS_140_3'] + + issues = [] + + # naive security provider check: specific three in specific order + observed_security_providers = ::Java::java.security.Security.getProviders.map(&:name) + expected_security_providers = %w(BCFIPS BCJSSE SUN) + if observed_security_providers != expected_security_providers + issues << "Java security providers are misconfigured (expected `#{expected_security_providers}`, observed `#{observed_security_providers}`)" + end + + # naive secure-random provider check: + observed_random_provider = ::Java::java.security.SecureRandom.new.getProvider.getName + expected_random_provider = "BCFIPS" + unless observed_random_provider == expected_random_provider + issues << "Java SecureRandom provider is misconfigured (expected `#{expected_random_provider}`; observed `#{observed_random_provider}`)" + end + + # ensure Bouncycastle is configured and ready + begin + unless Java::org.bouncycastle.crypto.CryptoServicesRegistrar.isInApprovedOnlyMode + issues << "Bouncycastle Crypto is not in 'approved-only' mode" + end + + unless ::Java::org.bouncycastle.crypto.fips.FipsStatus.isReady + issues << "Bouncycastle Crypto is not fips-ready" + end + rescue => ex + issues << "Bouncycastle Crypto unavailable: (#{ex.class}) #{ex.message}" + end + + # ensure non-compliant jruby openssl provider isn't registered + if org.jruby.ext.openssl.SecurityHelper.isProviderRegistered + issues << "non-compliant Jruby OpenSSL security helper is registered" + end + + if issues.any? + fail LogStash::ConfigurationError, "FIPS compliance issues: #{issues}" + end + end + end + end +end \ No newline at end of file diff --git a/x-pack/lib/x-pack/logstash_registry.rb b/x-pack/lib/x-pack/logstash_registry.rb index c1433580229..92a6efd72c6 100644 --- a/x-pack/lib/x-pack/logstash_registry.rb +++ b/x-pack/lib/x-pack/logstash_registry.rb @@ -7,8 +7,10 @@ xpack_modules.each do |name| $LOAD_PATH << File.join(LogStash::XPACK_PATH, "modules", name, "lib") end + require "logstash/plugins/registry" require "logstash/modules/util" +require "fips_validation/extension" if File.exist?(File.join(LogStash::XPACK_PATH, "lib/fips_validation/extension.rb")) require "monitoring/monitoring" require "monitoring/inputs/metrics" require "monitoring/outputs/elasticsearch_monitoring"