From a18d6e580d683ee858fd16429d2767696857d3d2 Mon Sep 17 00:00:00 2001 From: Konstantin Semenov Date: Fri, 3 Feb 2023 18:28:11 +0000 Subject: [PATCH 1/5] experiment: GCP CloudSQL certificates integration --- .../framework/cloud_sql_security_provider.rb | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 lib/java_buildpack/framework/cloud_sql_security_provider.rb diff --git a/lib/java_buildpack/framework/cloud_sql_security_provider.rb b/lib/java_buildpack/framework/cloud_sql_security_provider.rb new file mode 100644 index 0000000000..c2df0952f8 --- /dev/null +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +# Cloud Foundry Java Buildpack +# Copyright 2013-2020 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 'shellwords' +require 'tempfile' +require 'java_buildpack/component/versioned_dependency_component' +require 'java_buildpack/framework' +require 'java_buildpack/util/qualify_path' + +module JavaBuildpack + module Framework + + # Encapsulates the functionality for enabling zero-touch Safenet ProtectApp Java Security Provider support. + class CloudSqlSecurityProvider < JavaBuildpack::Component::VersionedDependencyComponent + include JavaBuildpack::Util + + # (see JavaBuildpack::Component::BaseComponent#compile) + def compile + download_zip false + + @droplet.copy_resources + + credentials = @application.services.find_service(FILTER, 'sslrootcert', 'sslcert', 'sslkey')['credentials'] + + pkcs12 = merge_client_credentials credentials + add_client_credentials pkcs12 + + add_trusted_certificates credentials['sslrootcert'] + end + + # (see JavaBuildpack::Component::BaseComponent#release) + def release + java_opts = @droplet.java_opts + + add_additional_properties(java_opts) + end + + protected + + # (see JavaBuildpack::Component::VersionedDependencyComponent#supports?) + def supports? + @application.services.one_service? FILTER, 'sslrootcert', 'sslcert', 'sslkey' + end + + private + + FILTER = /csb-google-mysql/.freeze + + private_constant :FILTER + + def add_additional_properties(java_opts) + java_opts + .add_system_property('javax.net.ssl.keyStore', keystore) + .add_system_property('javax.net.ssl.keyStorePassword', password) + end + + def add_client_credentials(pkcs12) + shell "#{keytool} -importkeystore -noprompt -destkeystore #{keystore} -deststorepass #{password} " \ + "-srckeystore #{pkcs12.path} -srcstorepass #{password} -srcstoretype pkcs12" \ + " -alias #{File.basename(pkcs12)}" + end + + def add_trusted_certificates(trusted_certificate) + File.open("#{@droplet.root}/ssl/certs/ca-certificates.crt", 'a') do |f| + f.write("#{trusted_certificate}\n") + end + end + + def ext_dir + @droplet.sandbox + 'ext' + end + + def keystore + @droplet.sandbox + 'cloud-sql-keystore.jks' + end + + def keytool + @droplet.java_home.root + 'bin/keytool' + end + + def merge_client_credentials(credentials) + certificate = write_certificate credentials['sslcert'] + private_key = write_private_key credentials['sslkey'] + + pkcs12 = Tempfile.new('pkcs12-') + pkcs12.close + + shell "openssl pkcs12 -export -in #{certificate.path} -inkey #{private_key.path} " \ + "-name #{File.basename(pkcs12)} -out #{pkcs12.path} -passout pass:#{password}" + + pkcs12 + end + + def password + 'cloud-sql-keystore-password' + end + + def write_certificate(certificate) + Tempfile.open('certificate-') do |f| + f.write "#{certificate}\n" + f.sync + f + end + end + + def write_private_key(private_key) + Tempfile.open('private-key-') do |f| + f.write "#{private_key}\n" + f.sync + f + end + end + + end + end +end From fa63df88d625f89cde416a869a43e879828cd9ff Mon Sep 17 00:00:00 2001 From: Konstantin Semenov Date: Fri, 3 Feb 2023 18:58:34 +0000 Subject: [PATCH 2/5] experiment: add logging --- .../framework/cloud_sql_security_provider.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/java_buildpack/framework/cloud_sql_security_provider.rb b/lib/java_buildpack/framework/cloud_sql_security_provider.rb index c2df0952f8..eabf688c6e 100644 --- a/lib/java_buildpack/framework/cloud_sql_security_provider.rb +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -31,6 +31,7 @@ class CloudSqlSecurityProvider < JavaBuildpack::Component::VersionedDependencyCo # (see JavaBuildpack::Component::BaseComponent#compile) def compile + log '#release'.yellow download_zip false @droplet.copy_resources @@ -45,6 +46,7 @@ def compile # (see JavaBuildpack::Component::BaseComponent#release) def release + log '#release'.yellow java_opts = @droplet.java_opts add_additional_properties(java_opts) @@ -54,6 +56,7 @@ def release # (see JavaBuildpack::Component::VersionedDependencyComponent#supports?) def supports? + log '#supports?'.yellow @application.services.one_service? FILTER, 'sslrootcert', 'sslcert', 'sslkey' end @@ -63,6 +66,10 @@ def supports? private_constant :FILTER + + def log(message) + puts "#{'===========>'.blue} #{'CloudSqlSecurityProvider'.red.bold} #{message}" + end def add_additional_properties(java_opts) java_opts .add_system_property('javax.net.ssl.keyStore', keystore) From e3bf11760f9cce26cc93d96e9775429587577324 Mon Sep 17 00:00:00 2001 From: Konstantin Semenov Date: Fri, 3 Feb 2023 19:04:53 +0000 Subject: [PATCH 3/5] Fix CA certificate path --- lib/java_buildpack/framework/cloud_sql_security_provider.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java_buildpack/framework/cloud_sql_security_provider.rb b/lib/java_buildpack/framework/cloud_sql_security_provider.rb index eabf688c6e..5ce8098618 100644 --- a/lib/java_buildpack/framework/cloud_sql_security_provider.rb +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -83,7 +83,7 @@ def add_client_credentials(pkcs12) end def add_trusted_certificates(trusted_certificate) - File.open("#{@droplet.root}/ssl/certs/ca-certificates.crt", 'a') do |f| + File.open("#{@droplet.root}/etc/ssl/certs/ca-certificates.crt", 'a') do |f| f.write("#{trusted_certificate}\n") end end From 86494a8f49ebe26fa61b8881d31d5f4da6cb05e5 Mon Sep 17 00:00:00 2001 From: Konstantin Semenov Date: Fri, 3 Feb 2023 19:18:54 +0000 Subject: [PATCH 4/5] Added security provider to the list --- config/cloud_sql_security_provider.yml | 18 +++++++++++ config/components.yml | 1 + .../framework/cloud_sql_security_provider.rb | 32 ++++++++++--------- .../cloud_sql_security_provider/index.yml | 0 4 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 config/cloud_sql_security_provider.yml create mode 100644 resources/cloud_sql_security_provider/index.yml diff --git a/config/cloud_sql_security_provider.yml b/config/cloud_sql_security_provider.yml new file mode 100644 index 0000000000..b5c97e95ef --- /dev/null +++ b/config/cloud_sql_security_provider.yml @@ -0,0 +1,18 @@ +# Cloud Foundry Java Buildpack +# Copyright 2013-2020 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. + +# Configuration for the CloudSql Security Provider framework +--- +enabled: true \ No newline at end of file diff --git a/config/components.yml b/config/components.yml index 933bf1a413..9ea64c7d2c 100644 --- a/config/components.yml +++ b/config/components.yml @@ -49,6 +49,7 @@ frameworks: - "JavaBuildpack::Framework::ClientCertificateMapper" - "JavaBuildpack::Framework::ContainerCustomizer" - "JavaBuildpack::Framework::ContainerSecurityProvider" + - "JavaBuildpack::Framework::CloudSqlSecurityProvider" - "JavaBuildpack::Framework::ContrastSecurityAgent" - "JavaBuildpack::Framework::DatadogJavaagent" - "JavaBuildpack::Framework::Debug" diff --git a/lib/java_buildpack/framework/cloud_sql_security_provider.rb b/lib/java_buildpack/framework/cloud_sql_security_provider.rb index 5ce8098618..740d5de42b 100644 --- a/lib/java_buildpack/framework/cloud_sql_security_provider.rb +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -18,21 +18,20 @@ require 'fileutils' require 'shellwords' require 'tempfile' -require 'java_buildpack/component/versioned_dependency_component' +require 'java_buildpack/component/base_component' require 'java_buildpack/framework' require 'java_buildpack/util/qualify_path' module JavaBuildpack module Framework - # Encapsulates the functionality for enabling zero-touch Safenet ProtectApp Java Security Provider support. - class CloudSqlSecurityProvider < JavaBuildpack::Component::VersionedDependencyComponent + # Encapsulates the functionality for enabling secure communication with GCP CloudSQL instances. + class CloudSqlSecurityProvider < JavaBuildpack::Component::BaseComponent include JavaBuildpack::Util # (see JavaBuildpack::Component::BaseComponent#compile) def compile - log '#release'.yellow - download_zip false + return unless supports? @droplet.copy_resources @@ -41,22 +40,26 @@ def compile pkcs12 = merge_client_credentials credentials add_client_credentials pkcs12 - add_trusted_certificates credentials['sslrootcert'] + add_trusted_certificate credentials['sslrootcert'] end # (see JavaBuildpack::Component::BaseComponent#release) def release - log '#release'.yellow + return unless supports? + java_opts = @droplet.java_opts add_additional_properties(java_opts) end + def detect + CloudSqlSecurityProvider.to_s.dash_case + end + protected # (see JavaBuildpack::Component::VersionedDependencyComponent#supports?) def supports? - log '#supports?'.yellow @application.services.one_service? FILTER, 'sslrootcert', 'sslcert', 'sslkey' end @@ -67,9 +70,6 @@ def supports? private_constant :FILTER - def log(message) - puts "#{'===========>'.blue} #{'CloudSqlSecurityProvider'.red.bold} #{message}" - end def add_additional_properties(java_opts) java_opts .add_system_property('javax.net.ssl.keyStore', keystore) @@ -82,10 +82,12 @@ def add_client_credentials(pkcs12) " -alias #{File.basename(pkcs12)}" end - def add_trusted_certificates(trusted_certificate) - File.open("#{@droplet.root}/etc/ssl/certs/ca-certificates.crt", 'a') do |f| - f.write("#{trusted_certificate}\n") - end + def add_trusted_certificate(trusted_certificate) + cert = Tempfile.new('ca-cert-') + cert.write(trusted_certificate) + cert.close + + shell "#{keytool} -import -trustcacerts -cacerts -storepass changeit -noprompt -alias CloudSQLCA -file #{cert.path}" end def ext_dir diff --git a/resources/cloud_sql_security_provider/index.yml b/resources/cloud_sql_security_provider/index.yml new file mode 100644 index 0000000000..e69de29bb2 From 04b69a816b40464f8525d7fcb61da2d0060241b6 Mon Sep 17 00:00:00 2001 From: Konstantin Semenov Date: Fri, 3 Feb 2023 22:16:57 +0000 Subject: [PATCH 5/5] [#184278537](https://www.pivotaltracker.com/story/show/184278537) --- lib/java_buildpack/framework/cloud_sql_security_provider.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/java_buildpack/framework/cloud_sql_security_provider.rb b/lib/java_buildpack/framework/cloud_sql_security_provider.rb index 740d5de42b..2c2acefe0b 100644 --- a/lib/java_buildpack/framework/cloud_sql_security_provider.rb +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -58,7 +58,6 @@ def detect protected - # (see JavaBuildpack::Component::VersionedDependencyComponent#supports?) def supports? @application.services.one_service? FILTER, 'sslrootcert', 'sslcert', 'sslkey' end @@ -90,10 +89,6 @@ def add_trusted_certificate(trusted_certificate) shell "#{keytool} -import -trustcacerts -cacerts -storepass changeit -noprompt -alias CloudSQLCA -file #{cert.path}" end - def ext_dir - @droplet.sandbox + 'ext' - end - def keystore @droplet.sandbox + 'cloud-sql-keystore.jks' end