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 90a12ec28e..af10f5b4b1 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/docs/framework-splunk_otel_java_agent.md b/docs/framework-splunk_otel_java_agent.md index e8b438376b..ef5fb1a10d 100644 --- a/docs/framework-splunk_otel_java_agent.md +++ b/docs/framework-splunk_otel_java_agent.md @@ -1,9 +1,8 @@ # Splunk Distribution of OpenTelemetry Java Instrumentation -The Splunk OpenTelemetry Java Agent buildpack framework will cause an application to be automatically instrumented -with the [Splunk distribution of OpenTelemetry Java Instrumentation](https://github.com/signalfx/splunk-otel-java). - -Trace data will be sent directly to Splunk Observability Cloud. +This buildpack framework automatically instruments your Java application +with the [Splunk distribution of OpenTelemetry Java Instrumentation](https://github.com/signalfx/splunk-otel-java) +to send trace data to Splunk Observability Cloud. @@ -16,15 +15,17 @@ Trace data will be sent directly to Splunk Observability Cloud.
-Tags are printed to standard output by the buildpack detect script +The buildpack detect script prints tags to standard output. ## User-Provided Service -Users are currently expected to `create-user-provided-service` (cups) of the collector -and bind it to their application. The service MUST contain the string `splunk-o11y`. +Users are currently expected to provide their own `user-provided-service` (cups) of the collector +and bind it to their application. + +The service name MUST contain the string `splunk-o11y`. For example, to create a service named `splunk-o11y` that represents Observability Cloud -realm `us0` and represents a user environment named `cf-demo`, you could use the following +realm `us0` and represents a user environment named `cf-demo`, use the following commands: ``` @@ -34,27 +35,29 @@ $ cf bind-service myApp splunk-o11y $ cf restage myApp ``` -The `credential` field of the service should provide these entries: +Provide the following values using the `credential` field of the service: | Name | Required? | Description |------------------------|-----------| ----------- -| `splunk.access.token` | Yes | The Splunk [org access token](https://docs.splunk.com/observability/admin/authentication-tokens/org-tokens.html). -| `splunk.realm` | Yes | The Splunk realm where data will be sent. This is commonly `us0` or `eu0` etc. -| `otel.*` or `splunk.*` | Optional | All additional credentials starting with these prefixes will be appended to the application's JVM arguments as system properties. +| `splunk.access.token` | Yes | Splunk [org access token](https://docs.splunk.com/observability/admin/authentication-tokens/org-tokens.html). +| `splunk.realm` | Yes | Splunk realm where data will be sent. This is commonly `us0`, `eu0`, and so on. See [Available regions or realms](https://docs.splunk.com/observability/en/get-started/service-description.html#available-regions-or-realms) for more information. +| `otel.*` or `splunk.*` | Optional | All additional credentials starting with these prefixes are appended to the application's JVM arguments as system properties. ### Choosing a version -Most users should skip this and simply use the latest version of the agent available (the default). -To override the default and choose a specific version, you can use the `JBP_CONFIG_*` mechanism +To override the default and choose a specific version, use the `JBP_CONFIG_*` mechanism and set the `JBP_CONFIG_SPLUNK_OTEL_JAVA_AGENT` environment variable for your application. -For example, to use version 1.16.0 of the Splunk OpenTelemetry Java Instrumentation, you -could run: +For example, to use version 1.16.0 of the Splunk OpenTelemetry Java Instrumentation, run: + ``` $ cf set-env testapp JBP_CONFIG_SPLUNK_OTEL_JAVA_AGENT '{version: 1.16.0}' ``` + +In most cases you can use the latest or default version of the agent available. # Additional Resources * [Splunk Observability](https://www.splunk.com/en_us/products/observability.html) +* [Official documentation of the Splunk Java agent](https://docs.splunk.com/observability/en/gdi/get-data-in/application/java/get-started.html) * [Splunk Distribution of OpenTelemetry Java](https://github.com/signalfx/splunk-otel-java) on GitHub 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..192adb19c1 --- /dev/null +++ b/lib/java_buildpack/framework/cloud_sql_security_provider.rb @@ -0,0 +1,135 @@ +# 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/base_component' +require 'java_buildpack/framework' +require 'java_buildpack/util/qualify_path' + +module JavaBuildpack + module Framework + + # 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 + return unless supports? + + @droplet.copy_resources + + credentials = @application.services.find_service(FILTER, 'sslrootcert', 'sslcert', 'sslkey')['credentials'] + + pkcs12 = merge_client_credentials credentials + add_client_credentials pkcs12 + + add_trusted_certificate credentials['sslrootcert'] + end + + # (see JavaBuildpack::Component::BaseComponent#release) + def release + return unless supports? + + java_opts = @droplet.java_opts + + add_additional_properties(java_opts) + end + + def detect + CloudSqlSecurityProvider.to_s.dash_case + end + + protected + + def supports? + @application.services.one_service? FILTER, 'sslrootcert', 'sslcert', 'sslkey' + end + + private + + FILTER = /csb-google-/.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_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 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 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