Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ To learn how to configure various properties of the buildpack, follow the "Confi
* Standard Frameworks
* [AppDynamics Agent](docs/framework-app_dynamics_agent.md) ([Configuration](docs/framework-app_dynamics_agent.md#configuration))
* [Container Customizer](docs/framework-container_customizer.md) ([Configuration](docs/framework-container_customizer.md#configuration))
* [Contrast Security Agent](docs/framework-contrast_security_agent.md) ([Configuration](docs/framework-contrast_security_agent.md#configuration))
* [Container Security Provider](docs/framework-container_security_provider.md) ([Configuration](docs/framework-container_security_provider.md#configuration))
* [Debug](docs/framework-debug.md) ([Configuration](docs/framework-debug.md#configuration))
* [Dyadic EKM Security Provider](docs/framework-dyadic_ekm_security_provider.md) ([Configuration](docs/framework-dyadic_ekm_security_provider.md#configuration))
Expand Down
1 change: 1 addition & 0 deletions config/components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ frameworks:
- "JavaBuildpack::Framework::AppDynamicsAgent"
- "JavaBuildpack::Framework::ContainerCustomizer"
- "JavaBuildpack::Framework::ContainerSecurityProvider"
- "JavaBuildpack::Framework::ContrastSecurityAgent"
- "JavaBuildpack::Framework::Debug"
- "JavaBuildpack::Framework::DyadicEkmSecurityProvider"
- "JavaBuildpack::Framework::DynatraceAppmonAgent"
Expand Down
19 changes: 19 additions & 0 deletions config/contrast_security_agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 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.

# Configuration for the ContrastSecurity framework
---
version: 3.+
repository_root: "https://artifacts.contrastsecurity.com/agents/java/"
41 changes: 41 additions & 0 deletions docs/framework-contrast_security_agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Contrast Security Agent Framework
The Contrast Security Agent Framework causes an application to be automatically configured to work with a bound [Contrast Security Service][].

<table>
<tr>
<td><strong>Detection Criterion</strong></td><td>Existence of a single bound Contrast Security service. The existence of an Contrast Security service defined by the <a href="http://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#VCAP-SERVICES"><code>VCAP_SERVICES</code></a> payload containing a service name, label or tag with <code>contrast-security</code> as a substring.
</td>
</tr>
</table>
Tags are printed to standard output by the buildpack detect script

## User-Provided Service
When binding ContrastSecurity using a user-provided service, it must have name or tag with `contrast-security` in it. The credential payload can contain the following entries:

| Name | Description
| ---- | -----------
| `teamserver_url` | The base URL in which your user has access to and the URL to which the Agent will report. ex: https://app.contrastsecurity.com
| `username` | The account name to use when downloading the agent
| `org_uuid` | The org uuid to send app information to, this is the org that your bound application will appear within
| `api_key` | Your user's api key
| `service_key` | Your user's service key


## Configuration
For general information on configuring the buildpack, including how to specify configuration values through environment variables, refer to [Configuration and Extension][].

The framework can be configured by modifying the [`config/contrast_security_agent.yml`][] file in the buildpack fork. The framework uses the [`Repository` utility support][repositories] and so it supports the [version syntax][] defined there.

| Name | Description
| ---- | -----------
| `repository_root` | The URL of the Contrast Security repository index ([details][repositories]).
| `version` | The version of Contrast Security to use. Candidate versions can be found in [this listing][].

[Contrast Security]: https://www.contrastsecurity.com
[Configuration and Extension]: ../README.md#configuration-and-extension
[Contrast Security Service]: https://www.contrastsecurity.com
[`config/contrast_security_agent.yml`]: ../config/contrast_security_agent.yml
[Configuration and Extension]: ../README.md#configuration-and-extension
[repositories]: extending-repositories.md
[this listing]: https://artifacts.contrastsecurity.com/agents/java/index.yml
[version syntax]: extending-repositories.md#version-syntax-and-ordering
112 changes: 112 additions & 0 deletions lib/java_buildpack/framework/contrast_security_agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Encoding: utf-8

# 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'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alphabetize the requirements list.

require 'java_buildpack/component/versioned_dependency_component'
require 'java_buildpack/framework'
require 'rexml/document'

module JavaBuildpack
module Framework

# Encapsulates the functionality for running the Contrast Security Agent support.
class ContrastSecurityAgent < JavaBuildpack::Component::VersionedDependencyComponent

# (see JavaBuildpack::Component::BaseComponent#compile)
def compile
download_jar(boot_class_name)
build_contrast_configuration
@droplet.copy_resources
end

# (see JavaBuildpack::Component::BaseComponent#release)
def release
app_name = @application.details['application_name'] || 'ROOT'
java_opts = @droplet.java_opts
java_opts.add_system_property('contrast.dir', '$TMPDIR')
java_opts.add_system_property('contrast.override.appname', app_name)
path = java_opts.qualify_path(@droplet.sandbox)
java_opts.add_preformatted_options("-javaagent:#{path}/#{boot_class_name}=#{path}/contrast.config")
end

protected

# (see JavaBuildpack::Component::VersionedDependencyComponent#supports?)
def supports?
@application.services.one_service?(CONTRAST_FILTER, TEAMSERVER_URL, USERNAME, API_KEY, SERVICE_KEY)
end

private

API_KEY = 'api_key'.freeze
CONTRAST_FILTER = 'contrast-security'.freeze
SERVICE_KEY = 'service_key'.freeze
TEAMSERVER_URL = 'teamserver_url'.freeze
USERNAME = 'username'.freeze

private_constant :API_KEY
private_constant :CONTRAST_FILTER
private_constant :SERVICE_KEY
private_constant :TEAMSERVER_URL
private_constant :USERNAME

PLUGIN_PACKAGE = 'com.aspectsecurity.contrast.runtime.agent.plugins.'.freeze

def credentials
@application.services.find_service(CONTRAST_FILTER)['credentials']
end

def boot_class_name
version = @version.to_s.split('_')[0]
"contrast-engine-#{version}.jar"
end

def build_contrast_configuration

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this one to you to decide, but making a real live XML document might not be the easiest or clearest way to do this. Another option is to use extended literals and just write clear text that you know to be valid XML. An example. It's up to you though, and if you think this is easier, I'm happy to leave it as-is.

doc = REXML::Document.new
contrast = doc.add_element('contrast')
(contrast.add_element 'id').add_text('default')
(contrast.add_element 'global-key').add_text(credentials[API_KEY])
user = contrast.add_element('user')
(user.add_element 'id').add_text(credentials[USERNAME])
(user.add_element 'key').add_text(credentials[SERVICE_KEY])
(contrast.add_element 'url').add_text("#{credentials[TEAMSERVER_URL]}/Contrast/s/")
(contrast.add_element 'results-mode').add_text('never')

add_plugins(contrast)

contrast_config.open(File::CREAT | File::WRONLY) { |f| f.write(doc) }
end

def add_plugins(config)
plugin_package = 'com.aspectsecurity.contrast.runtime.agent.plugins.'
plugin_group = config.add_element('plugins')
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.security.SecurityPlugin")
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.architecture.ArchitecturePlugin")
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.appupdater.ApplicationUpdatePlugin")
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.sitemap.SitemapPlugin")
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.frameworks.FrameworkSupportPlugin")
(plugin_group.add_element 'plugin').add_text("#{plugin_package}.http.HttpPlugin")
end

def contrast_config
@droplet.sandbox + 'contrast.config'
end

end

end
end
Empty file.
71 changes: 71 additions & 0 deletions spec/java_buildpack/framework/contrast_security_agent_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Encoding: utf-8

# Cloud Foundry Java Buildpack
# Copyright 2013-2016 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 'spec_helper'
require 'component_helper'
require 'java_buildpack/framework/contrast_security_agent'
require 'java_buildpack/util/tokenized_version'

describe JavaBuildpack::Framework::ContrastSecurityAgent do
include_context 'component_helper'
let(:configuration) do
{ 'teamserver_url' => 'a_url',
'org_uuid' => '12345',
'username' => 'contrast_user',
'api_key' => 'api_test',
'service_key' => 'service_test' }
end

it 'does not detect without contrastsecurity service' do
expect(component.detect).to be_nil
end

context do
before do
allow(services).to receive(:one_service?).with(/contrast[-]?security/,
'teamserver_url','username', 'api_key', 'service_key').and_return(true)
allow(services).to receive(:find_service).and_return('credentials' => :configuration)
end

it 'detects with contrastsecurity service' do
expect(component.detect).to eq("contrast-security-agent=#{version}")
end

it 'downloads Contrast Security agent JAR',
cache_fixture: 'stub-contrast-security-agent.jar' do

component.compile
expect(sandbox + 'contrast-engine-0.0.0.jar').to exist
end

it 'updates JAVA_OPTS' do
component.release

expect(java_opts).to include('-javaagent:$PWD/.java-buildpack/contrast_security_agent/contrast-engine-0.0.0.jar'\
'=$PWD/.java-buildpack/contrast_security_agent/contrast.config')
expect(java_opts).to include('-Dcontrast.dir=$TMPDIR')
expect(java_opts).to include('-Dcontrast.override.appname=test-application-name')
end

it 'created contrast.config',
cache_fixture: 'stub-contrast-security-agent.jar' do
component.compile
expect(sandbox + 'contrast.config').to exist
end
end

end