This Cloud Foundry service broker is designed to be chained in front-of other service brokers and dynamically open security groups to let apps bound to service instance emmit outgoing traffic to IP addresses returned in the chained service instances credentials.
This is a similar broker chain as proposed into https://github.com/cloudfoundry-community/cf-subway
# 1st deploy an upstream target broker accessible through its route: mysql-broker.mydomain.org.
# Don't register the target broker in CF (the filter broker offering will be registered instead)
[...]
# then deploy sec-group-broker-filter and configure it to proxy traffic to the target broker:
# you may want to deploy sec-group-broker-filter using cloudfoundry:
$ vi manifest.yml
---
applications:
- name: sec-group-broker-filter
memory: 256M
instances: 1
path: sec-group-broker-filter-<version>.jar
# URL to register into the marketplace
host: sec-group-chained-mysql-broker
domain: mydomain.org
env:
# Where to send received traffic: URL to the target broker.
BROKER_FILTER_URL=https://mysql-broker.mydomain.org
# basic auth credentials to use while sending traffic to the target broker
BROKER_FILTER_USER=user
BROKER_FILTER_PASSWORD=password
# Optionally restrict the IPs/ports in created security groups to a set of trusted destinations.
# In case the target broker gets compromised and returns unrelated IPs in credentials, the binding response
# will error, preventing unathorized accesses to unrelated destinations.
# Trusted destinations is expressed as either a single IP address (10.0.11.0), an IP address range (e.g. 10.0.11.1-10.0.11.2),
# or a CIDR block (e.g. 10.0.11.0/24).
# If empty or unspecified, any IP adress returned from the binding response will be granted access in
# created security groups
BROKER_FILTER_TRUSTED_DESTINATION_HOSTS=192.0.1.0-192.0.2.0
# An optional trusted destination ports. Can be a single port, multiple comma-separated ports, or a single range of ports.
# Examples: 3306 3306,3307 3300-3400
# If empty or unspecified, any port returned from the binding response
# will be granted access in created security groups
BROKER_FILTER_TRUSTED_DESTINATION_PORTS=3306
# CloudFoundry CC api host
CLOUDFOUNDRY_HOST: api.yourdomain.com
# CloudFoudry user with Org admin privileges on orgs where services will be bound
CLOUDFOUNDRY_USER: admin
# CloudFoudry user password
CLOUDFOUNDRY_PASSWORD: password
# Optionally enable that both the filter broker offering and target broker offering coexist in the marketplace
# To avoid conflicts in service offering id from both, the filter broker offering will have the specified suffix added
#BROKER_FILTER_SERVICEOFFERING_SUFFIX=-sec
# deploy the broker
$ cf push
# register the broker
$ cf create-service-broker mysql user mypwd https://sec-group-chained-mysql-broker.mydomain.org
# expose the service in the marketplace
$ cf enable-service-access mysql -o myorg
The protocol, FQDN or IP addresses, and TCP ports are extracted from the credentials returned by the chained broker from the standard fields:
- URI
- host
- port
Support for additional fields would be added later (e.g memcache-release's vip
or servers
list)
The FQDN is looked up and resolved into a set of IP addresses.
The prococol is currently always mapped to tcp
. In the future, some well known protocol could be mapped to udp
instead
For example, in the following credentials hash,
{
"name": "ad_c6f4446532610ab",
"hostname": "us-cdbr-east-03.cleardb.com",
"port": "3306",
"username": "b5d435f40dd2b2",
"password": "ebfc00ac",
"uri": "mysql://b5d435f40dd2b2:ebfc00ac@us-cdbr-east-03.cleardb.com:3306/ad_c6f4446532610ab",
"jdbcUrl": "jdbc:mysql://b5d435f40dd2b2:ebfc00ac@us-cdbr-east-03.cleardb.com:3306/ad_c6f4446532610ab"
}
the FQDN us-cdbr-east-03.cleardb.com would be resolved into 141.8.225.68, 141.8.225.69
The resulting security group opened would be:
[
{"protocol":"tcp","destination":"141.8.225.68/31","ports":"3306"}
]
In order to be protected against a compromise filtered service broker (e.g. p-mysql) (that would return unowned, unrelated IPs in the binding response), IP/port range can be restricted. Set following env properties to restrict IP/port range.
# An optional trusted IPs: single IP address, IP address range (e.g. 192.0.1.0-192.0.2.0), or a CIDR block to allow security groups to. If empty or unspecified, any IP adress returned from the binding response will be granted access in created security groups
BROKER_FILTER_TRUSTED_DESTINATION_HOSTS=192.0.1.0-192.0.2.0
# An optional trusted port range. If empty or unspecified, any port returned from the binding response will be granted access in created security groups
BROKER_FILTER_TRUSTED_DESTINATION_PORTS=
The bugs and features enhancements are managed through github issues, possibly through huboard to have overview of milestones.
The project depends on Java 14. To build from source and install to your local Maven cache, run the following:
$ ./mvnw clean install
The integration tests deploy sec-group-broker-filter as a space-scoped service broker and expect a sample service broker to delegate to (e.g. static-cred-broker).
The integration validates the deployment of sec-group-broker-filter, registers is as a space-scoped service broker, verify it has a service offering matching the backing broker service offering, and instanciates a service instance. Note that currently, the network ACL to the service binding are not yet asserted, see related #14
Note that since this does not require CF admin permissions, such tests can run on a public CF instance such as PWS.
To run the integration tests, run the following:
$ ./mvnw -Pintegration-test \
-Dtest.apiHost=... \
-Dtest.username=... \
-Dtest.password=... \
-Dtest.proxy.host=... \
-Dtest.proxy.password=... \
-Dtest.proxy.port=... \
-Dtest.proxy.username=... \
-Dtest.skipSslValidation=... \
-Dtest.org=... \
-Dtest.domain=... \
-Dbroker.filter.url=... \
-Dbroker.filter.user=... \
-Dbroker.filter.password=... \
clean test
IMPORTANT Integration tests should be run against an empty Cloud Foundry instance. The integration tests are destructive, affecting nearly everything on an instance given the chance.
The integration tests require a running instance of Cloud Foundry to test against. To configure the integration tests with the appropriate connection information use the following environment variables:
Name | Description |
---|---|
TEST_APIHOST |
The host of Cloud Foundry instance. Typically something like api.local.pcfdev.io . |
TEST_USERNAME |
The test user's name |
TEST_PASSWORD |
The test user's password |
TEST_SKIPSSLVALIDATION |
Whether to skip SSL validation when connecting to the Cloud Foundry instance. Typically true when connecting to a PCF Dev instance. |
TEST_ORG |
The Org used for test suite |
TEST_DOMAIN |
The Domain used for test suite |
Prereqs: checkout the branch to release (master), and make sure it is up-to-date w.r.t. the github remote.
Releasing is made using maven release plugin as follows :
$ mvn release:prepare --batch-mode -Dtag={your git tag} -DreleaseVersion={release version to be set} -DdevelopmentVersion={next snapshot version to be set}
# ex : mvn release:prepare --batch-mode -Dtag=v2.3.0.RELEASE -DreleaseVersion=2.3.0.RELEASE -DdevelopmentVersion=2.4.0.BUILD
The jar file is available there : <your_workspace>/service-broker-filter-securitygroups/target/service-broker-filter-securitygroups-{release version}.jar
# ex : ./service-broker-filter-securitygroups/target/service-broker-filter-securitygroups-2.3.0.RELEASE.jar
You must upload manually this jar file
Following the release:
- edit the release notes in github
- clean up your local workspace using
mvn release:clean
In case of issues, try:
mvn release:rollback
(which creates a new commit reverting changes)- possibly revert the commits in git (
git reset --hard commitid
),
- possibly revert the commits in git (
- clean up the git tag
git tag -d vXX && git push --delete origin vXX
, mvn release:clean
- fix the root cause and retry.
This work has been inspired by the cf-subway great idea contributed by Dr Nic. This repo tries to extend this idea into flexible framework for reusable filters/facade, see service-broker-filter-core subproject.
When some legacy services exposed in the marketplace need to be protected at the level 3/4 (IP/TCP) and level 7 authentication through provided credentials is not sufficient (e.g. vulnerable to denial of service or brute force password attacks).
In this case, the default security groups don't let apps reach the IP adresses ranges where such legacy services are exposed. This broker dynamically creates and assigns security groups to access services returned in credentials.
Initially the FQDN are resolved into IP addresses when binding is requested, which translates into an application security group (ASG) being created for the space. The resulting ASG is currently not updated afterwards.
A future evolution could be to periodically (at the end of the TTL period) lookup the IP address and update the corresponding security group. This would also require a rolling update of the bound application containers, as the New security rules apply to new containers as they are created, but not to containers that are already running when the rules are created.
Yes, add as many routes to the sec-group-broker-filter as there are up stream brokers, each with its own configuration entries.