diff --git a/.idea/dictionaries/bhale.xml b/.idea/dictionaries/bhale.xml
index 42f7cc42eb..bf6ad475e0 100644
--- a/.idea/dictionaries/bhale.xml
+++ b/.idea/dictionaries/bhale.xml
@@ -65,6 +65,7 @@
myhost
mypass
myuser
+ networkaddress
newrelic
newrelicagent
overweaving
diff --git a/.rubocop.yml b/.rubocop.yml
index 236b840043..e9846b9ead 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -31,9 +31,9 @@ Metrics/CyclomaticComplexity:
Metrics/LineLength:
Max: 120
Metrics/MethodLength:
- Max: 20
+ Max: 25
Metrics/ParameterLists:
- Max: 8
+ Max: 10
Metrics/PerceivedComplexity:
Max: 10
RSpec/ExampleLength:
diff --git a/config/components.yml b/config/components.yml
index ec8c8ff1f0..13e389518b 100644
--- a/config/components.yml
+++ b/config/components.yml
@@ -66,5 +66,5 @@ frameworks:
- "JavaBuildpack::Framework::SpringInsight"
- "JavaBuildpack::Framework::YourKitProfiler"
- "JavaBuildpack::Framework::TakipiAgent"
- - "JavaBuildpack::Framework::SecurityProviders"
+ - "JavaBuildpack::Framework::JavaSecurity"
- "JavaBuildpack::Framework::JavaOpts"
diff --git a/lib/java_buildpack/buildpack.rb b/lib/java_buildpack/buildpack.rb
index e7083fa7c0..0a19c140d5 100644
--- a/lib/java_buildpack/buildpack.rb
+++ b/lib/java_buildpack/buildpack.rb
@@ -23,6 +23,7 @@
require 'java_buildpack/component/immutable_java_home'
require 'java_buildpack/component/java_opts'
require 'java_buildpack/component/mutable_java_home'
+require 'java_buildpack/component/networking'
require 'java_buildpack/component/security_providers'
require 'java_buildpack/logging/logger_factory'
require 'java_buildpack/util/cache/application_cache'
@@ -131,6 +132,7 @@ def initialize(app_dir, application)
'env_vars' => Component::EnvironmentVariables.new(app_dir),
'extension_directories' => Component::ExtensionDirectories.new(app_dir),
'java_opts' => @java_opts,
+ 'networking' => Component::Networking.new,
'security_providers' => Component::SecurityProviders.new
}
@@ -181,7 +183,7 @@ def instantiate(components, java_home, component_info)
droplet: Component::Droplet.new(component_info['additional_libraries'], component_id,
component_info['env_vars'], component_info['extension_directories'],
java_home, component_info['java_opts'], component_info['app_dir'],
- component_info['security_providers'])
+ component_info['networking'], component_info['security_providers'])
}
component.constantize.new(context)
end
diff --git a/lib/java_buildpack/component/droplet.rb b/lib/java_buildpack/component/droplet.rb
index 4f602a8434..db8f90a4b3 100644
--- a/lib/java_buildpack/component/droplet.rb
+++ b/lib/java_buildpack/component/droplet.rb
@@ -56,6 +56,10 @@ class Droplet
# @return [JavaOpts] the shared +JavaOpts+ instance for all components
attr_reader :java_opts
+ # @!attribute [r] networking
+ # @return [Networking] the shared +Networking+ instance for all components
+ attr_reader :networking
+
# @!attribute [r] root
# @return [JavaBuildpack::Util::FilteringPathname] the root of the droplet's fileystem filtered so that it
# excludes files in the sandboxes of other components
@@ -83,10 +87,11 @@ class Droplet
# be an instance of +MutableJavaHome+. Otherwise it should
# be an instance of +ImmutableJavaHome+.
# @param [JavaOpts] java_opts the shared +JavaOpts+ instance for all components
+ # @param [Networking] networking the shared +Networking+ instance for all components
# @param [Pathname] root the root of the droplet
# @param [SecurityProviders] security_providers the shared +SecurityProviders+ instance for all components
def initialize(additional_libraries, component_id, env_vars, extension_directories, java_home, java_opts, root,
- security_providers)
+ networking, security_providers)
@additional_libraries = additional_libraries
@component_id = component_id
@@ -110,6 +115,7 @@ def initialize(additional_libraries, component_id, env_vars, extension_directori
->(path) { !in?(path, buildpack_root) || in?(path, @sandbox) },
true
)
+ @networking = networking
@security_providers = security_providers
end
diff --git a/lib/java_buildpack/component/networking.rb b/lib/java_buildpack/component/networking.rb
new file mode 100644
index 0000000000..7809ba3345
--- /dev/null
+++ b/lib/java_buildpack/component/networking.rb
@@ -0,0 +1,54 @@
+# Cloud Foundry Java Buildpack
+# Copyright 2013-2017 the original author or authors.
+#
+# 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 'fileutils'
+require 'java_buildpack/component'
+
+module JavaBuildpack
+ module Component
+
+ # An abstraction around the networking configuration provided to a droplet by components.
+ #
+ # A new instance of this type should be created once for the application.
+ class Networking
+
+ # @!attribute [rw] networkaddress_cache_ttl
+ # @return [Integer] the number of seconds to cache the successful lookup
+ attr_accessor :networkaddress_cache_ttl
+
+ # @!attribute [rw] networkaddress_cache_negative_ttl
+ # @return [Integer] the number of seconds to cache the failure for un-successful lookups
+ attr_accessor :networkaddress_cache_negative_ttl
+
+ # Write the networking configuration to a destination file
+ #
+ # @param [Pathname] destination the destination to write to
+ # @return [Void]
+ def write_to(destination)
+ FileUtils.mkdir_p destination.parent
+
+ destination.open(File::CREAT | File::APPEND | File::WRONLY) do |f|
+ f.write "networkaddress.cache.ttl=#{@networkaddress_cache_ttl}\n" if @networkaddress_cache_ttl
+
+ if @networkaddress_cache_negative_ttl
+ f.write "networkaddress.cache.negative.ttl=#{networkaddress_cache_negative_ttl}\n"
+ end
+ end
+ end
+
+ end
+
+ end
+end
diff --git a/lib/java_buildpack/component/security_providers.rb b/lib/java_buildpack/component/security_providers.rb
index df7f26fcdd..097f118ccf 100644
--- a/lib/java_buildpack/component/security_providers.rb
+++ b/lib/java_buildpack/component/security_providers.rb
@@ -31,7 +31,7 @@ class SecurityProviders < Array
def write_to(destination)
FileUtils.mkdir_p destination.parent
- destination.open(File::CREAT | File::WRONLY) do |f|
+ destination.open(File::CREAT | File::APPEND | File::WRONLY) do |f|
each_with_index { |security_provider, index| f.write "security.provider.#{index + 1}=#{security_provider}\n" }
end
end
diff --git a/lib/java_buildpack/framework/security_providers.rb b/lib/java_buildpack/framework/java_security.rb
similarity index 91%
rename from lib/java_buildpack/framework/security_providers.rb
rename to lib/java_buildpack/framework/java_security.rb
index 12a4e1b7ef..89e4d5b2e3 100644
--- a/lib/java_buildpack/framework/security_providers.rb
+++ b/lib/java_buildpack/framework/java_security.rb
@@ -21,15 +21,16 @@ module JavaBuildpack
module Framework
# Encapsulates the functionality for contributing custom Security Providers to an application.
- class SecurityProviders < JavaBuildpack::Component::BaseComponent
+ class JavaSecurity < JavaBuildpack::Component::BaseComponent
# (see JavaBuildpack::Component::BaseComponent#detect)
def detect
- SecurityProviders.to_s.dash_case
+ JavaSecurity.to_s.dash_case
end
# (see JavaBuildpack::Component::BaseComponent#compile)
def compile
+ @droplet.networking.write_to java_security
@droplet.security_providers.write_to java_security
end
diff --git a/lib/java_buildpack/jre/open_jdk_like_jre.rb b/lib/java_buildpack/jre/open_jdk_like_jre.rb
index 424687050b..839db2865d 100644
--- a/lib/java_buildpack/jre/open_jdk_like_jre.rb
+++ b/lib/java_buildpack/jre/open_jdk_like_jre.rb
@@ -13,10 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+require 'ipaddr'
require 'fileutils'
require 'java_buildpack/component/versioned_dependency_component'
require 'java_buildpack/jre'
require 'java_buildpack/util/tokenized_version'
+require 'resolv'
module JavaBuildpack
module Jre
@@ -48,6 +50,7 @@ def detect
def compile
download_tar
@droplet.copy_resources
+ disable_dns_caching if link_local_dns?
return if @droplet.java_home.java_8_or_later?
@@ -62,6 +65,25 @@ def release
.add_system_property('java.io.tmpdir', '$TMPDIR')
end
+ private
+
+ LINK_LOCAL = IPAddr.new('169.254.0.0/16').freeze
+
+ private_constant :LINK_LOCAL
+
+ def disable_dns_caching
+ puts ' JVM DNS caching disabled in lieu of BOSH DNS caching'
+
+ @droplet.networking.networkaddress_cache_ttl = 0
+ @droplet.networking.networkaddress_cache_negative_ttl = 0
+ end
+
+ def link_local_dns?
+ Resolv::DNS::Config.new.lazy_initialize.nameserver_port.any? do |nameserver_port|
+ LINK_LOCAL.include? IPAddr.new(nameserver_port[0])
+ end
+ end
+
end
end
diff --git a/spec/droplet_helper.rb b/spec/droplet_helper.rb
index 18490ee3ea..f85e860910 100644
--- a/spec/droplet_helper.rb
+++ b/spec/droplet_helper.rb
@@ -22,6 +22,7 @@
require 'java_buildpack/component/extension_directories'
require 'java_buildpack/component/immutable_java_home'
require 'java_buildpack/component/java_opts'
+require 'java_buildpack/component/networking'
require 'java_buildpack/component/security_providers'
require 'java_buildpack/util/snake_case'
require 'pathname'
@@ -38,7 +39,8 @@
let(:droplet) do
JavaBuildpack::Component::Droplet.new(additional_libraries, component_id, environment_variables,
- extension_directories, java_home, java_opts, app_dir, security_providers)
+ extension_directories, java_home, java_opts, app_dir, networking,
+ security_providers)
end
let(:extension_directories) { JavaBuildpack::Component::ExtensionDirectories.new app_dir }
@@ -62,6 +64,8 @@
java_opts
end
+ let(:networking) { JavaBuildpack::Component::Networking.new }
+
let(:security_providers) { JavaBuildpack::Component::SecurityProviders.new }
before do
diff --git a/spec/fixtures/framework_java_security_networking b/spec/fixtures/framework_java_security_networking
new file mode 100644
index 0000000000..60738b2246
--- /dev/null
+++ b/spec/fixtures/framework_java_security_networking
@@ -0,0 +1,4 @@
+networkaddress.cache.ttl=-1
+networkaddress.cache.negative.ttl=-2
+security.provider.1=test-security-provider-1
+security.provider.2=test-security-provider-2
diff --git a/spec/fixtures/framework_java_security_security_providers b/spec/fixtures/framework_java_security_security_providers
new file mode 100644
index 0000000000..b4e7d7fc84
--- /dev/null
+++ b/spec/fixtures/framework_java_security_security_providers
@@ -0,0 +1,2 @@
+security.provider.1=test-security-provider-1
+security.provider.2=test-security-provider-2
diff --git a/spec/java_buildpack/framework/security_providers_spec.rb b/spec/java_buildpack/framework/java_security_spec.rb
similarity index 58%
rename from spec/java_buildpack/framework/security_providers_spec.rb
rename to spec/java_buildpack/framework/java_security_spec.rb
index aaac041450..050298461e 100644
--- a/spec/java_buildpack/framework/security_providers_spec.rb
+++ b/spec/java_buildpack/framework/java_security_spec.rb
@@ -16,28 +16,40 @@
require 'spec_helper'
require 'component_helper'
require 'fileutils'
-require 'java_buildpack/framework/security_providers'
+require 'java_buildpack/framework/java_security'
-describe JavaBuildpack::Framework::SecurityProviders do
+describe JavaBuildpack::Framework::JavaSecurity do
include_context 'component_helper'
it 'adds extension directories to system properties' do
component.release
- expect(java_opts).to include('-Djava.ext.dirs=$PWD/.java-buildpack/security_providers/test-extension-directory-1:' \
- '$PWD/.java-buildpack/security_providers/test-extension-directory-2')
+ expect(java_opts).to include('-Djava.ext.dirs=$PWD/.java-buildpack/java_security/test-extension-directory-1:' \
+ '$PWD/.java-buildpack/java_security/test-extension-directory-2')
end
- it 'writes new security properties' do
+ it 'writes security provider security properties' do
component.compile
expect(sandbox + 'java.security').to exist
+ expect(File.read(sandbox + 'java.security'))
+ .to eq File.read('spec/fixtures/framework_java_security_security_providers')
+ end
+
+ it 'writes networking security properties' do
+ networking.networkaddress_cache_ttl = -1
+ networking.networkaddress_cache_negative_ttl = -2
+
+ component.compile
+
+ expect(sandbox + 'java.security').to exist
+ expect(File.read(sandbox + 'java.security')).to eq File.read('spec/fixtures/framework_java_security_networking')
end
it 'adds security properties to system properties' do
component.release
- expect(java_opts).to include('-Djava.security.properties=$PWD/.java-buildpack/security_providers/' \
+ expect(java_opts).to include('-Djava.security.properties=$PWD/.java-buildpack/java_security/' \
'java.security')
end
diff --git a/spec/java_buildpack/jre/open_jdk_like_jre_spec.rb b/spec/java_buildpack/jre/open_jdk_like_jre_spec.rb
index 3504ac04c7..dba74a01d8 100644
--- a/spec/java_buildpack/jre/open_jdk_like_jre_spec.rb
+++ b/spec/java_buildpack/jre/open_jdk_like_jre_spec.rb
@@ -17,6 +17,7 @@
require 'component_helper'
require 'java_buildpack/component/mutable_java_home'
require 'java_buildpack/jre/open_jdk_like_jre'
+require 'resolv'
describe JavaBuildpack::Jre::OpenJDKLikeJre do
include_context 'component_helper'
@@ -49,4 +50,26 @@
expect(java_opts).to include('-Djava.io.tmpdir=$TMPDIR')
end
+ it 'does not disable dns caching if no BOSH DNS',
+ cache_fixture: 'stub-java.tar.gz' do
+
+ component.detect
+ component.compile
+
+ expect(networking.networkaddress_cache_ttl).not_to be
+ expect(networking.networkaddress_cache_negative_ttl).not_to be
+ end
+
+ it 'disables dns caching if BOSH DNS',
+ cache_fixture: 'stub-java.tar.gz' do
+
+ allow_any_instance_of(Resolv::DNS::Config).to receive(:nameserver_port).and_return([['169.254.0.2', 53]])
+
+ component.detect
+ component.compile
+
+ expect(networking.networkaddress_cache_ttl).to eq 0
+ expect(networking.networkaddress_cache_negative_ttl).to eq 0
+ end
+
end