Securing Service Credentials with Runtime CredHub

Page last updated:

Warning: Pivotal Operations Manager v2.4 is no longer supported because it has reached the End of General Support (EOGS) phase as defined by the Support Lifecycle Policy. To stay up to date with the latest software and security updates, upgrade to a supported version.

This topic describes how to develop your Pivotal Cloud Foundry (PCF) service tile to support secure service instance (SSI) credentials using Runtime CredHub. For more information about Runtime CredHub, see Runtime CredHub in the CredHub topic.

Background

When developers bind an app to a service instance, the binding typically includes binding credentials required to access the service.

In PCF v2.0 and later, service brokers can store binding credentials as SSI credentials in runtime CredHub and apps can retrieve these credentials from CredHub. This secures service instance credential management by avoiding the following:

  • Leaking environment variables to logs, which increases risk of disclosure.
  • Sending credentials between components, which increases risk of disclosure.
  • Requiring users to rotate credentials through the environment, which requires container recreation.

To store binding credentials in runtime CredHub, your service tile needs to support the following:

  • Discover the location of runtime CredHub.
  • Provide this CredHub location to the broker app. The service broker uses the provided location to store binding credentials in CredHub.
  • Enable operators to select the SSI credentials option in the tile UI.

Difference between SSI and Internal Service Credentials

SSI credentials, which let apps access services through service instances, are distinct from the credentials that service tiles store in BOSH CredHub for their own internal use.

When a service uses SSI credentials, its service broker stores the binding credentials in runtime CredHub. Then, when PAS binds an app to an instance of the service, the broker retrieves the credentials from runtime CredHub and delivers them to the Cloud Controller (CC) to enable the app to access the service.

These SSI credentials are different from credentials that the tile uses internally, for example, to give the service broker access to an internal database. PAS generates the internal tile credentials for a service when the service is first installed and stores them in BOSH CredHub, not runtime CredHub.

For more information on the CredHub credential management component, see the CredHub documentation topic.

The sections below describe an example implementation of how to add SSI credentials functionality to a service tile.

Step 1: Modify Your BOSH Release

To use runtime CredHub, your service tile needs to retrieve the location of the CredHub server, which is published in the Pivotal Application Service (PAS) tile, through a BOSH link.

Note: BOSH Links let multiple jobs share deployment-time configuration properties. This helps to avoid redundant configurations in BOSH releases and deployment manifests. For more information about BOSH Links, see BOSH Links.

Update Spec File and Templates

The location of runtime CredHub is stored in the credhub.internal_url and credhub.port properties of the PAS tile. To enable your service tile to retrieve these CredHub-provided properties, add a consumes: section with the BOSH link from the PAS tile to the spec file of the BOSH job that will use them and edit the job’s templates to access the values in the link:

    consumes:
    - {name: credhub, type: credhub}

For information about using BOSH Links in the spec file and templates of a job and consuming shared properties provided by other jobs, see Links in Spec Files and Links in Templates.

Save the Runtime CredHub Location

To use the runtime CredHub location retrieved from the PAS tile, you must write a post_deploy tile errand that saves the value out in some way and enables the service broker to access it.

Depending on how your tile deploys the service broker app, the service instance errand can save the CredHub location in different ways. If the tile pushes the broker as a Cloud Foundry app, the errand can store the location in an environment variable such as CREDHUB_URL for the service broker to call. If BOSH deploys the service broker outside of of PAS, the errand could write the CredHub location out to a templated configuration file that the service broker reads.

Update Deployment Manifest

In the BOSH release for your tile, edit the deployment manifest .yml file so that it contains the BOSH link to CredHub:

- name: broker      
  release: my-broker-release
  consumes:
    credhub:
      from: credhub
      deployment: cf-XXXXXXXXX

For more information about using BOSH links in deployment manifests, see Links in Manifests

Step 2: Enable Your Tile to Find Runtime CredHub

To enable your service tile to discover runtime CredHub, edit your product template so that it consumes the location of CredHub. See the following example:

job_types:
- name: JOB-NAME
  resource_label: LABEL-NAME
  templates:
  - name: TEMPLATE-NAME
    release: RELEASE-NAME
    consumes: |
      credhub: {from: credhub, deployment: "(( ..cf.deployment_name ))"}

You can also use the address from the BOSH link to verify that the CredHub server is available at that address during tile installation. See the following example:

properties:
      aliases:
        (( dig credhub.service.cf.internal @169.254.0.2 )):
        - '*.credhub.(( ..cf.credhub.network )).(( ..cf.deployment_name )).bosh'

In the example, the runtime CredHub instance can be accessed at credhub.service.cf.internal. If your broker runs as an app, you can resolve this address with BOSH DNS. If your broker runs on a VM with a Consul agent, you can resolve the address with Consul. Alternatively, from a VM, you can resolve the address with dig credhub.service.cf.internal @169.254.0.2. This command uses the PAS BOSH DNS server to do lookup.

Step 3: Provide Operators with the Choice to Use CredHub

To provide operators with the choice to select the SSI credentials option, edit your product template. See the following example:

form_types:
- name: FORM-NAME
  label: LABEL-NAME
  description: DESCRIPTION
  property_inputs:
  - reference: .JOB-NAME.secure_credentials
    label: Secure service instance credentials
    description: "When checked, service instance credentials are stored in CredHub. Enable only when installing with PCF v2.0 or later and this feature is also enabled in the PAS tile."

property_blueprints:
  - name: hidden_credhub_selector
    type: selector
    configurable: false
    default: "default"
    option_templates:
      - name: default_option
        select_value: "default"
        named_manifests:
          - name: consumes_section_credhub_disabled
            manifest: |
              credhub: nil
          - name: consumes_section_credhub_enabled
            manifest: |
              credhub: {from: credhub, deployment: "(( ..cf.deployment_name ))"}

job_types:
- name: JOB-NAME
  resource_label: LABEL-NAME
  templates:
  - name: TEMPLATE-NAME
    release: RELEASE-NAME
    consumes: |
      "(( secure_credentials.value ? .properties.hidden_credhub_selector.selected_option.parsed_manifest(consumes_section_credhub_enabled) : .properties.hidden_credhub_selector.selected_option.parsed_manifest(consumes_section_credhub_disabled) ))"
  errand: true
  resource_definitions:
     ...
  property_blueprints:
  ...
  - name: secure_credentials
    type: boolean
    configurable: true
    default: false

Step 4: Store Binding Credentials in Runtime CredHub

When the CC receives a request to bind a service instance to an app, it forwards the request to the service broker. The service broker then returns the binding credentials that allow access to the service.

To enable your service broker to store binding credentials in runtime CredHub and make them SSI credentials, do the following:

  1. In your service broker code, locate where your broker handles binding requests from the CC.

  2. Add code that authenticates your service broker to CredHub using OAuth2 tokens from UAA. Each call to the CredHub API must include an authorization header. For more information about CredHub authentication, see the Authentication section of the CredHub API documentation.

  3. Update your code to store your binding credentials in CredHub using the CredHub API endpoint for setting the json credential type with a user-provided value. See the following example for how to format your API call:

    curl "https://CREDHUB.INTERNAL_URL:CREDHUB.PORT/api/v1/data" \
    -X PUT \
    -d '{
      "name": "/c/CLIENT-IDENTIFIER/SERVICE-IDENTIFIER/BINDING-GUID/CREDENTIAL-NAME",
      "type": "json",
      "value": {
        "uri": "SERVICE-URL",
        "username": "USERNAME",
        "password": "PASSWORD"
      }
     }' \
    -H 'Content-type: application/json'
    

    Where:

    • CREDHUB.INTERNAL_URL and CREDHUB.PORT are the address and port of CredHub.
    • CLIENT-IDENTIFIER is a value provided by the service broker to uniquely identify the broker.
    • SERVICE-IDENTIFIER is the name of the service offering as shown in the services catalog.
    • BINDING-GUID is the GUID created by the CC and passed to the service broker in the service binding request.
    • CREDENTIAL-NAME is a value provided by the service broker to name the credential.
    • SERVICE-URL is the URL of your service.
    • USERNAME and PASSWORD are your binding credentials.

    For further reference, see the Set Credentials section of the CredHub API documentation.

  4. Grant your application permission to read the credential from CredHub:

    curl "https://CREDHUB.INTERNAL_URL:CREDHUB.PORT/api/v2/permissions" \
    -X POST \
    -d '
    {
    "path": "/c/CLIENT-IDENTIFIER/SERVICE-IDENTIFIER/BINDING-GUID/CREDENTIAL-NAME",
    "actor": "mtls-app:APP-GUID"
    "operations": ["read"]
    }' \
    -H "authorization: bearer [TOKEN]" \
    -H 'content-type: application/json'
    

    Where:

    • APP-GUID is the GUID of the CF application being used
  5. Modify your service broker so that it returns a reference to the stored credentials in response to the binding request from the CC. Return the credentials as a single key credhub-ref with its value formatted as /c/CLIENT-IDENTIFIER/SERVICE-IDENTIFIER/BINDING-GUID/CREDENTIAL-NAME. For example, the binding response might look like the following:

    {
    "credentials": {
      "credhub-ref": "/c/example-service-broker/example-service/faa677f5-25cd-4f1e-8921-14a9d5ab48b8/credentials"
    }
    }
    

Note: Java Virtual Machine (JVM) apps can use Spring CredHub to access the CredHub API.