This project provides a configuration management for Open Service Broker API broker implementations, enabling sharing of service brokers among multiple OSB client platoforms. See orange-cloudfoundry/paas-templates#492 for more background around use-cases and considered alternatives.
The following diagram presents a functional overview of the ocb-cdmb feature scope
The features are supported by coarse gain components used by osb-cmdb:
Osb-cmdb is an OSB facade that provides the following features to service admins:
In addition, Osb-cmdb handle OSB API viriants such as K8S svcat duplicated calls, protecting service broker authors from having to deal with each OSB api variations. See #17 for more details.
The osb-cdmb service broker translates received osb calls into equivalent CF CC API calls
OSB API endpoint | eq CF CLI UX |
---|---|
GET /v2/catalog | cf marketplace |
PUT /v2/service_instances/:instance_id | cf create-space ; cf create-service; cf7 set-label; cf7 set-annotation |
GET /v2/service_instances/:instance_id/last_operation | cf service |
GET /v2/service_instances/:instance_id | cf service (WIP) |
PATCH /v2/service_instances/:instance_id | cf update-service |
DELETE /v2/service_instances/:instance_id | cf delete-service |
PUT /v2/service_instances/:instance_id/service_bindings/:binding_id | cf create-service-key |
GET /v2/service_instances/:instance_id/service_bindings/:binding_id/last_operation | cf get-service-key (WIP) |
GET /v2/service_instances/:instance_id/service_bindings/:binding_id | cf get-service-key |
DELETE /v2/service_instances/:instance_id/service_bindings/:binding_id | cf delete-service-key |
Osb-cmdb ships as a spring-boot jar which is configured using properties.
curl -L https://github.com/orange-cloudfoundry/osb-cmdb-spike/releases/download/v0.9.0/osb-cmdb-0.9.0.jar -o ./osb-cmdb.jar
java \
-Dspring.cloud.appbroker.deployer.cloudfoundry.api-host=api.redacted-domain.org \
-Dspring.cloud.appbroker.deployer.cloudfoundry.api-port=443 \
-Dspring.cloud.appbroker.deployer.cloudfoundry.default-org=osb-cmdb-services-org-client-0 \
-Dspring.cloud.appbroker.deployer.cloudfoundry.default-space=p-mysql \
-Dspring.cloud.appbroker.deployer.cloudfoundry.username=redacted \
-Dspring.cloud.appbroker.deployer.cloudfoundry.password=redacted \
-Dspring.security.user.name=user \
-Dspring.security.user.password=password \
-Dosbcmdb.admin.user=user \
-Dosbcmdb.admin.password=password \
-Dosbcmdb.dynamic-catalog.enabled=true \
-Dosbcmdb.dynamic-catalog.catalog.services.suffix=suffix \
-Dosbcmdb.dynamic-catalog.catalog.services.excludeBrokerNamesRegexp=".*cmdb.*" \
-Dosbcmdb.broker.propagateMetadataAsCustomParam=true \
-Dosbcmdb.broker.hideMetadataCustomParamInGetServiceInstanceEndpoint=true \
-Dlogging.level.cloudfoundry-client=DEBUG \
-Dlogging.level.cloudfoundry-client.operations=DEBUG \
-Dlogging.level.org.springframework.cloud.appbroker=debug \
-Dlogging.level.org.springframework.cloud.appbroker.deployer.cloudfoundry=debug \
-Dlogging.level.org.springframework.cloud.servicebroker=debug \
-jar ./osb-cmdb.jar
Osb-cmdb adds support for additional properties which are illustrated below. Source of truth is associated unit tests, e.g. SecurityConfigTest
Osb-cmdb requires two users auth to be configured:
spring.security.user
: used for OSB API callsosbcmdb.admin
: used to access sensitive supportability endpoints (powered by springboot actuators)Osb-Cmdb expects to be deployed once per OSB client, each having its own basic authentication, its own brokered services catalog, and backend services organization.
In production like in acceptance tests, use spring boot actuator logger to dynamically increase log levels,
curl -kv https://admin:password@test-broker-app-create-instance-with-service-keys.redacted-domain/actuator/loggers/cloudfoundry-client.wire -X POST -H 'Content-Type: application/json' -d '{"configuredLevel": "TRACE"}'
With the following log levels
logger | level |
---|---|
cloudfoundry-client.operations | debug |
cloudfoundry-client.request | debug |
cloudfoundry-client.response | debug |
cloudfoundry-client.wire | trace |
We observe wire traces such as
20-04-2020 16:46:35.395 [cloudfoundry-client-epoll-4] DEBUG cloudfoundry-client.request.request - GET /v2/spaces/TEST-SPACE-GUID/service_instances?q=name:instance-id&page=1&return_user_provided_service_instances=true
20-04-2020 16:46:35.401 [cloudfoundry-client-epoll-4] TRACE cloudfoundry-client.wire.log - [id: 0x5cc929b8, L:/127.0.0.1:44870 - R:localhost/127.0.0.1:8080] READ: 574B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d |HTTP/1.1 200 OK.|
|00000010| 0a 4d 61 74 63 68 65 64 2d 53 74 75 62 2d 49 64 |.Matched-Stub-Id|
|00000020| 3a 20 39 35 39 35 34 65 66 30 2d 62 34 66 36 2d |: 95954ef0-b4f6-|
|00000030| 34 33 61 38 2d 61 39 63 35 2d 36 35 39 66 39 63 |43a8-a9c5-659f9c|
|00000040| 37 61 33 36 64 37 0d 0a 56 61 72 79 3a 20 41 63 |7a36d7..Vary: Ac|
|00000050| 63 65 70 74 2d 45 6e 63 6f 64 69 6e 67 2c 20 55 |cept-Encoding, U|
|00000060| 73 65 72 2d 41 67 65 6e 74 0d 0a 43 6f 6e 74 65 |ser-Agent..Conte|
|00000070| 6e 74 2d 45 6e 63 6f 64 69 6e 67 3a 20 67 7a 69 |nt-Encoding: gzi|
|00000080| 70 0d 0a 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f |p..Transfer-Enco|
|00000090| 64 69 6e 67 3a 20 63 68 75 6e 6b 65 64 0d 0a 53 |ding: chunked..S|
|000000a0| 65 72 76 65 72 3a 20 4a 65 74 74 79 28 39 2e 34 |erver: Jetty(9.4|
|000000b0| 2e 32 37 2e 76 32 30 32 30 30 32 32 37 29 0d 0a |.27.v20200227)..|
[...]
Osb-cmdb exposes springboot actuator http traces through the last 100 requests stored in memory. Load the following endpoint in your browser: https://admin:password@osb-cmdb-broker-1.redacted-domain/actuator/httptrace
Load the following endpoint in your browser: https://admin:password@osb-cmdb-broker-1.redacted-domain/actuator/
to get the currently list of actuator endpoints enabled.
Backing services register with osb-cmdb using the CF CLI commands for managing service brokers, i.e cf create-service-broker SERVICE_BROKER USERNAME PASSWORD URL
and then enabling the plans on the backing service organization (configured with the spring.cloud.appbroker.deployer.cloudfoundry.default-org
property) associated with each osb-cmdb deployment cf enable-service-access SERVICE [-b BROKER] [-p PLAN] [-o ORG]
.
Osb-cmdb operators might consider using terraform with the cloudfoundry-community/terraform-provider-cf for using a declarative approach, see cloudfoundry_service_broker and cloudfoundry_service_access resources
Osb-cmdb supports a statically configured catalog of brokered services, by setting osbcmdb.dynamic-catalog.enabled=false
, and configuring the spring-cloud-open-service-broker catalog.
Following is an example of a simple spring-cloud-open-service-broker catalog configuration (without detailed catalog customization)
#### Manual catalog and brokered service configuration
spring:
cloud:
openservicebroker:
catalog:
services:
- name: p-mysql-cmdb
id: ebca66fd-461d-415b-bba3-5e379d671c88
description: A useful service
bindable: true
plan_updateable: true
tags:
- example
plans:
- name: 10mb
id: p-mysql-cmdb-10mb
description: A standard plan
free: true
- name: 20mb
id: p-mysql-cmdb-20mb
description: A standard plan
free: true
With large marketplace being brokered, manually maintaining the catalog might be a tedious task.
Osb-Cmdb brings the feature of dynamic catalog generation. This feature is enabled by default, and can be opted-out if necessary.
At start up, the broker will fetch the service definitions from the target CF instance, as visible from the default organization and space (the equivalent of the cf marketplace
command). For now service plan visibility is not fetched.
As a result, a catalog of Brokered services is generated with a one-to-one mapping between brokered services and backing services. The following properties can be used to tune this mapping:
osbcmdb:
dynamic-catalog:
enabled: "true" #Turned on by default. Enables dynamic catalog. Catalog and brokered services properties
catalog:
services:
suffix: "-cmdb" #Suffix to add each service definition
excludeBrokerNamesRegexp: ".*cmdb.*" # Excludes broker names matching this regexp. Good to excluding osb-cmdb itself to avoid brokering itself.
Additionally, the generated catalog is dumped on disk onto /tmp/osb-cmdb-dynamicCatalog.yml
(see org.springframework.cloud.appbroker.autoconfigure.ServiceConfigurationYamlDumper)
This can be used as a baseline for manually tuned catalog when supported tunings in automated generation are insufficient.
The following table further documents the options and their default values:
property name | default value | description |
---|---|---|
osbcmdb.dynamic-catalog.enabled | true | enables dynamic catalog when set to true |
osbcmdb.dynamic-catalog.catalog.services.suffix | null | when set, adds a suffix to every service definition names |
osbcmdb.dynamic-catalog.catalog.services.excludeBrokerNamesRegexp | null | when set, exclude service brokers from dynamic catalog whose name match the specified java regular expression |
The following figure displays a hierarchical cloudfoundry org/space/service instance|binding|key organization before osb-cmdb startups and apply its SpacePerServiceDefinition
strategy
01 ├── osb-cmdb-backend-services-org-client-0
02 │ ├── default
04 └── osb-cmdb-smoke-test-brokered-services-org-client-0
05 ├── smoke-tests
06 └── default
Osb-cmdb provides smoke tests in the paas-templates repo that uses CF as an OSB client to send OSB API calls to osb-cmdb.
Following consumption of brokered services by smoke tests, Osb-cmdb have dynamically created spaces/service instances and service keys as described into Functional overview
01 ├── osb-cmdb-backend-services-org-client-0
02 │ ├── default
03 │ ├── cassandra
04 │ └── mysql
05 │ ├── mysql-service-instance-guid1
06 │ └── mysql-service-key-guid1
07 ├── osb-cmdb-brokered-services-org-client-0
08 ├── default
09 └── smoke-tests
10 ├── mysql-service-instance-1
11 └── mysql-service-binding-1
cf create-service instance mysql-cmdb 10mb myinstance
by smoke tests
cf bind-service myapp myinstance
by smoke tests
This section describes the use-cases and associated cloudfoundry roles that each actor should be granted
Actor | Use case | Permission | Details |
---|---|---|---|
cmdb-operator | deploy cmdb | space developer on the cmdb broker space | -- |
cmdb-operator | run smoke tests | space developer on the smoke test space | -- |
cmdb-operator | inspect whole cmdb content | Global auditor | -- |
cmdb-operator | troubleshoot/fix cmdb content | space developer on each cmdb space or cloud_controller.admin | -- |
osb platform consummers | inspect cmdb content for their tenant | space auditor on each cmdb space of their tenant alternatively global editor | -- |
osb service provider | inspect cmdb content for their service | space auditor on each cmdb space of their service offerings alternatively global editor | -- |
osb service provider | register/update their brokers/service plans | cloud-controller.admin or delegated permission through 3rd party tooling (*) | -- |
osb service provider | manage service plan visibility | cloud-controller.admin or delegated permission through 3rd party tooling (*) | -- |
(*) See related pending work at https://github.com/orange-cloudfoundry/paas-templates/issues/792
To assign global auditor role, refer to uaa-user-management.html#global-auditor doc
$ uaac group add cloud_controller.global_auditor
[...]
$ uaac member add cloud_controller.global_auditor a-osb-platform-user-name
In order to provide traceability from backing services to brokered services, the backing service instances are attached the following metadata:
Label name | Label value | Query usage | Read usage |
---|---|---|---|
backing_service_instance_guid | backing-service-instance-guid | used internally by osb-cmdb as a workaround for lack of support for service instance read endpoint, in order to get service instance params | |
brokered_service_instance_guid | brokered-service-guid | find a backend service by brokered-service-guid in all orgs/spaces | (redundant with backend service instance name) |
brokered_service_context_organization_guid | brokered-service-meta-org-guid | find all backing services for a brokered_service_context_organization_guid | lookup org guid for a given backing service |
brokered_service_context_space_guid | brokered-service-meta-space-guid | find all backing services for a brokered-service-space-guid | lookup space guid for a given backing service |
brokered_service_originating_identity_user_id | brokered-service X-Broker-API-Originating-Identity | find all backing services for a brokered-service-user-guid | lookup user guid for a given backing service |
Annotation name | Annotation value | Read usage | |
---|---|---|---|
brokered_service_context_organization_name | N/A | lookup org name for a given backing service | |
brokered_service_context_space_name | N/A | lookup space name for a given backing service | |
brokered_service_context_instance_name | N/A | lookup service instance name for a given backing service | |
brokered_service_api_info_location | X-Api-Info-Location header | N/A | enforce dashboards authN and authZ |
(*) annotations can not be queried in CF
To lookup metadata attached to a backing service instance, scripts is available at https://github.com/orange-cloudfoundry/cf-cli-cmdb-scripts to workaround incomplete CF V3 API and CF V7 CLI
# Example of a backing service being looked up (corresponding to a brokered service instance provisionned by a CF OSB client)
$ cf s
Getting services in org osb-cmdb-backend-services-org-client-0 / space p-mysql as xx...
name service plan bound apps last operation broker upgrade available
3aa96c94-1d01-4389-ab4f-260d99257215 p-mysql 10mb create succeeded p-mysql
$ cf_labels_service 80134f9b-b6fd-48e2-8ca5-e185c4cb5ce0
{
"labels": {
"brokered_service_instance_guid": "3aa96c94-1d01-4389-ab4f-260d99257215",
"brokered_service_context_organization_guid": "c2169b61-9360-4d67-968c-575f3a10edf5",
"brokered_service_originating_identity_user_id": "0d02117b-aa21-43e2-b35e-8ad6f8223519",
"brokered_service_context_space_guid": "1a603476-a3a1-4c32-8021-d2a7b9b7c6b4",
"backing_service_instance_guid": "191260bb-3477-422d-8f40-bf053ccf6930"
},
"annotations": {
"brokered_service_context_instance_name": "osb-cmdb-broker-0-smoketest-1578565892",
"brokered_service_context_space_name": "smoke-tests",
"brokered_service_api_info_location": "api.mycf.org/v2/info",
"brokered_service_context_organization_name": "osb-cmdb-brokered-services-org-client-0"
}
}
# Example of a backing service being looked up (corresponding to a brokered service instance provisionned by a K8S OSB client)
$ cf s
Getting services in org osb-cmdb-backend-services-org-client-0 / space p-mysql as xx...
name service plan bound apps last operation broker upgrade available
b6a7a748-6fa5-497c-b111-a3a727ec88db p-mysql 10mb create succeeded p-mysql
$ cf_labels_service b6a7a748-6fa5-497c-b111-a3a727ec88db
Metadata for service b6a7a748-6fa5-497c-b111-a3a727ec88db:
{
"labels": {
"brokered_service_instance_guid": "b6a7a748-6fa5-497c-b111-a3a727ec88db",
"brokered_service_originating_identity_uid": "",
"brokered_service_context_namespace": "cloudfoundry-service-instances",
"backing_service_instance_guid": "6ea3cf73-cbb6-46be-b9c5-dbcf7b04064f"
},
"annotations": {
"brokered_service_originating_identity_extra": "{\"scopes.authorization.openshift.io\":[\"user:full\"]}",
"brokered_service_originating_identity_username": "a-user-name",
"brokered_service_originating_identity_groups": "[\"system:authenticated:oauth\",\"system:authenticated\"]"
}
}
The svcat in OpenShift v3.9.51 ( Kubernetes v1.9.1+a0ce1bc657 ), does not provide its internal id (wbv8r
in the example below) in its OSB calls. Correlation from svcat requires looking up the OSB service instance guid, named ExternalId
into svcat cli
$ svcat get instances
NAME NAMESPACE CLASS PLAN STATUS
+---------------------+--------------------------------+---------------+--------------+--------+
noop-ondemand-jkpn4 cloudfoundry-service-instances noop-ondemand mysql-sample Ready
p-mysql-wbv8r cloudfoundry-service-instances p-mysql 10mb Ready
$ svcat describe instance p-mysql-wbv8r -v 9 2>&1 | grep "Response Body" | sed 's/.*Response Body: //' | grep ServiceInstance | jq .spec.externalID
"b6a7a748-6fa5-497c-b111-a3a727ec88db"
#Lookup in the cmdb a K8S provisionned instance from its externalID
$ cf curl "/v3/service_instances?label_selector=brokered_service_instance_guid==b6a7a748-6fa5-497c-b111-a3a727ec88db" | jq .resources[]
{
"guid": "6ea3cf73-cbb6-46be-b9c5-dbcf7b04064f",
"created_at": "2020-02-27T17:35:43Z",
"updated_at": "2020-02-27T17:35:43Z",
"name": "b6a7a748-6fa5-497c-b111-a3a727ec88db",
"relationships": {
"space": {
"data": {
"guid": "38de12e4-3fc8-4698-a8b0-87e7a3dbf2ed"
}
}
},
"metadata": {
"labels": {
"brokered_service_instance_guid": "b6a7a748-6fa5-497c-b111-a3a727ec88db",
"brokered_service_originating_identity_uid": "",
"brokered_service_context_namespace": "cloudfoundry-service-instances",
"backing_service_instance_guid": "6ea3cf73-cbb6-46be-b9c5-dbcf7b04064f"
},
"annotations": {
"brokered_service_originating_identity_extra": "{\"scopes.authorization.openshift.io\":[\"user:full\"]}",
"brokered_service_originating_identity_username": "a-user-name",
"brokered_service_originating_identity_groups": "[\"system:authenticated:oauth\",\"system:authenticated\"]"
}
},
"links": {
"space": {
"href": "https://api.redacted.com/v3/spaces/38de12e4-3fc8-4698-a8b0-87e7a3dbf2ed"
}
}
}
OSB clients maintain a cache of the brokered service instance data returned from the OSB provisionning endpoint. In particular, this includes the dashboard url.
Whenever the backing service dashboard url changes and needs to be reflected to brokered service instance fetched by OSB clients, OSB clients can request for a service instance upgrade.
Additionally, the 0.x version of osb-cmdb used to not propagate backing service instance dashboard to brokered services. Starting with 1.1.0 version, osb-cmdb can be opted-in to bump the maintenance_info object within the served catalog, which enables users to upgrade brokered services without backing services supporting upgrades. The following configuration properties control the maintenance-info behavior:
property name | default value | example value | description |
---|---|---|---|
osbcmdb.maintenanceinfo.version | null | 1.1.0 | set as version if backing service has no maintenance_info.version, merged through addition otherwise |
osbcmdb.maintenanceinfo.description | null | osb-cmdb now propagates dashboard url | set as description if backing service has no maintenance_info.description, merged through string concat with LF otherwise |
The OSB API specifications available at https://github.com/openservicebrokerapi/servicebroker/blob/master/spec.md are versatile and support multiple extensions. See https://github.com/openservicebrokerapi/servicebroker/blob/master/diagram.md for a visual overview.
This section lists the requirements that osb clients need to comply with in order to consumme services exposed by osb-cmdb.
Once OSB 2.16 version gets released and supported by osb-cmdb, the following additional fields MAY be used by clients to fill in arbitrary meta-data associated with service instances, see https://github.com/openservicebrokerapi/servicebroker/pull/658 for background:
These annotations get propagated into service monitoring/alerts.
By default, when propagating OSB calls to backing service brokers, osb-cmdb adds an extra x-osb-cmdb
param to the service instance provisionning call containing additional metadata matching the inventory metadata and an additional brokered_service_client_name
property identifying the calling osb client, whose value matches the name of the backing service instance organization name. This can be opted-out with the osbcmdb.broker.propagateMetadataAsCustomParam=false
flag
Note that by default, this x-osb-cmdb
param isn't returned by the service instance fetch endpoint. This can be opted-out with osbcmdb.broker.hideMetadataCustomParamInGetServiceInstanceEndpoint=false
flag
{
"x-osb-cmdb": {
"annotations": {
"brokered_service_context_spaceName": "smoke-tests",
"brokered_service_context_organizationName": "osb-cmdb-brokered-services-org-client-0",
"brokered_service_api_info_location": "api.redacted-domain.com/v2/info",
"brokered_service_context_instanceName": "osb-cmdb-broker-0-smoketest-1600699922",
"brokered_service_client_name": "osb-cmdb-backend-services-org-client-1",
"brokered_service_context_organization_annotations": "{\"domain.com/org-key1\":\"org-value1\",\"orange.com/overrideable-key\":\"org-value2\"}",
"brokered_service_context_space_annotations": "{\"domain.com/space-key1\":\"space-value1\",\"domain.com/space-key2\":\"space-value2\"}",
"brokered_service_context_instance_annotations": "{\"domain.com/instance-key1\":\"instance-value1\",\"orange.com/overrideable-key\":\"instance-value2\"}"
},
"labels": {
"brokered_service_instance_guid": "7d9235c5-242d-4b17-ac82-935f121ffd7f",
"brokered_service_context_organization_guid": "c2169b61-9360-4d67-968c-575f3a10edf5",
"brokered_service_originating_identity_user_id": "0d02117b-aa21-43e2-b35e-8ad6f8223519",
"brokered_service_context_space_guid": "1a603476-a3a1-4c32-8021-d2a7b9b7c6b4",
"brokered_service_context_orange_overrideable-key": "instance-value2"
}
}
}
Note that the CloudFoundry annotations with prefix "orange.com/" are automatically merged in precedence order (org/space/instance) into a key with the "orange.com/" prefix trimmed (brokered_service_context_orange_overrideable-key
in the example below)
{
"annotations": {
"brokered_service_originating_identity_extra": "{\"scopes.authorization.openshift.io\":[\"user:full\"]}",
"brokered_service_originating_identity_username": "a-user-name",
"brokered_service_originating_identity_groups": "[\"system:authenticated:oauth\",\"system:authenticated\"]",
"brokered_service_client_name": "osb-cmdb-backend-services-org-client-1"
},
"labels": {
"brokered_service_instance_guid": "b6a7a748-6fa5-497c-b111-a3a727ec88db",
"brokered_service_originating_identity_uid": "",
"brokered_service_context_namespace": "cloudfoundry-service-instances"
}
}
UIs/Dashboard presented to developers (e.g. quotas and in the future backup/restore and monitoring) use OpenIdConnect (https://openid.net/specs/openid-connect-core-1_0.html) for user authentication (AuthN) and a REST endpoint for authorization (AuthZ). This is inspired from https://docs.cloudfoundry.org/services/dashboard-sso.html
This section below detail how osb-cmdb discovers the OIDC and AuthZ from Osb API calls:
Osb-cmdb expects to receive the X-Api-Info-Location header in all OSB API calls. This header documented at https://docs.cloudfoundry.org/services/supporting-multiple-cf-instances.html (until this header makes it into the OSB API, see cf https://github.com/openservicebrokerapi/servicebroker/pull/686 )
The X-Api-Info-Location header MUST return a Url (similar to https://api.cloudfoundry.redacted-domain.org/v2/info ) whose response should have header « Content-Type: application/json;charset=utf-8 » and a body at least containing the following field keys, (and appropriate values).
{ "authorization_endpoint": "https://login.redacted-domain.org", "token_endpoint": "https://uaa.redacted-domain.org", }
These 2 fields provide access to OIDC authorization and token endpoints.
The clients are expected to comply with the Cloudfoundry catalogue extension documented at https://github.com/openservicebrokerapi/servicebroker/blob/master/profile.md#cloud-foundry-catalog-extensions with an extract reproduced below.
{ "services": [{ "name": "fake-service", "id": "acb56d7c-XXXX-XXXX-XXXX-feb140a59a66", "description": "A fake service.", "dashboard_client": { "id": "398e2f8e-XXXX-XXXX-XXXX-19a71ecbcf64", "secret": "277cabb0-XXXX-XXXX-XXXX-7822c0a90e5d", "redirect_uri": "http://localhost:1234" } }] }
Clients are expected to provision an OAuth2 client matching the id/secret and restrict http redirections to the specified redirect_uri.
The OSB-CMDB directs users into an Oauth2 authorization grant flow (see https://tools.ietf.org/html/rfc6749#section-4.1 and CF UAA implementation at https://docs.cloudfoundry.org/api/uaa/version/74.4.0/index.html#authorization-code-grant ) with the following authorize endpoint parameters
response_type= code
client_id: the oauth client claimed in the catalog cloudfoundry extension described above.
redirect_uri
scope=cloud_controller_service_permissions.read openid
state
nonce
This authorization grant flow grants the OSB-CMDB with an access token which is then used for invoking the authorization REST endpoint.
This authorization grant flow may also provide the OSB-CMDB with an OIDC id token, used to fetch developer identity (in Id token standard claims https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims or UserInfo endpoint https://openid.net/specs/openid-connect-core-1_0.html#UserInfo ). This may be used in the future in audit events.
Below is an extract from the OAuth2 specifications describing the authorization grant flow interactions
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(B)-- User authenticates --->| Server |
| | | |
| -+----(C)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(A) (C) | |
| | | |
^ v | |
+---------+ | |
| |>---(D)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(E)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)
Note: The lines illustrating steps (A), (B), and (C) are broken into
two parts as they pass through the user-agent.
Figure 3: Authorization Code Flow
The flow illustrated in Figure 3 includes the following steps:
(A) The client initiates the flow by directing the resource owner's
user-agent to the authorization endpoint. The client includes
its client identifier, requested scope, local state, and a
redirection URI to which the authorization server will send the
user-agent back once access is granted (or denied).
(B) The authorization server authenticates the resource owner (via
the user-agent) and establishes whether the resource owner
grants or denies the client's access request.
(C) Assuming the resource owner grants access, the authorization
server redirects the user-agent back to the client using the
redirection URI provided earlier (in the request or during
client registration). The redirection URI includes an
authorization code and any local state provided by the client
earlier.
(D) The client requests an access token from the authorization
server's token endpoint by including the authorization code
received in the previous step. When making the request, the
client authenticates with the authorization server. The client
includes the redirection URI used to obtain the authorization
code for verification.
(E) The authorization server authenticates the client, validates the
authorization code, and ensures that the redirection URI
received matches the URI used to redirect the client in
step (C). If valid, the authorization server responds back with
an access token and, optionally, a refresh token.
A distinct AuthZ endpoint GET /v2/service_instances/:guid/permissions (matching https://apidocs.cloudfoundry.org/12.1.0/service_instances/retrieving_permissions_on_a_service_instance.html ) MUST be supported and available at the same FQDN than the Url retourned by the X-Api-Info-Location header.
This endpoint will receive a JWT OAuth2 bearer access token provided by developers browser in its web session when accessing the dashboard (see section above)
The osb-cmdb will authenticate users accessing dashboards using OIDC and the AuthZ endpoint. The user AuthZ will be performed according to the AuthZ endpoint response which MUST respond with the following JSON formatted response
{ "manage": true, "read": true }
When a K8S OSB client (such as service catalog) requires authorization of K8S users, the osb-cmdb plans to leverage the K8S SubjectAccessReview endpoint https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/subject-access-review-v1/ for checking the permissions of SVCat resource associated wth the OSB provisionned service instance
From https://kubernetes.io/docs/reference/access-authn-authz/authorization/#checking-api-access
SelfSubjectAccessReview is part of the authorization.k8s.io API group, which exposes the API server authorization to external services. Other resources in this group include: SubjectAccessReview - Access review for any user, not only the current one. Useful for delegating authorization decisions to the API server.
The following diagram summarizes the interactions between OSB-CMDB and its clients (inspired by https://gist.github.com/hrchu/d88efb56e72534a1233d16f36eb3e3e9)
This project initially spiked and inspired from the great spring-cloud/spring-cloud-app-broker project. After attempting upstream contribution in spring-cloud-app-broker
to support osb-cmdb use-cases, see #6 and related issue spring-cloud/spring-cloud-app-broker/#285, a redesign and reimplementation of osb-cmdb independently of spring-cloud-app-broker
was conducted in version 1.0, see #13. Osb-cmdb 1.0 still uses some app-broker configuration (prefixed with spring.cloud.appbroker.
, acceptance and component-test code fragments, referenced with acronym SCAB below.
Design docs, and implementation notes are available in the osb-cmdb/docs/impl-notes directory
Circle ci tests run offline without a cloudfoundry instance. They include scab tests and osb-cmdb tests. See osb-cmdb/.circle/config.yml
Acceptance tests run privately against a live cloudfoundry instance. Tests are private because it is hard to secure logs to not leak credentials that could be used to abuse the Cloud Foundry instance.
See https://github.com/orange-cloudfoundry/osb-cmdb-ci for the concourse task running the acceptance tests.
Like scab, osb-cmdb acceptance tests use distinct properties than osb-cmdb production properties. Refer to Getting started for the list of prod properties supported, and paas-templates smoke tests.
See more details in spring-cloud-app-broker-acceptance-tests/README.adoc
gradle.properties
(e.g version=1.1.0
), commit & pushosb-cmdb/gradle.properties
, commit & push e.g. version=0.2.0.BUILD-SNAPSHOT
osbcmdb-1.0.0.jar
)