Skip to content

Read service bindings from a file - #37

Merged
norman-abramovitz merged 3 commits into
masterfrom
file-based-service-bindings
Jul 28, 2026
Merged

Read service bindings from a file#37
norman-abramovitz merged 3 commits into
masterfrom
file-based-service-bindings

Conversation

@norman-abramovitz

Copy link
Copy Markdown
Contributor

Closes #28.

The failure this fixes

With the file-based-vcap-services app feature enabled, Cloud Foundry sets
VCAP_SERVICES_FILE_PATH and does not set VCAP_SERVICES at all. New
then unmarshalled an empty string, so cfenv.Current() failed outright on
every such app — not a missing convenience, a hard error.

The feature exists because bindings can exceed the environment variable size
limit (RFC-0030).

Precedence, and where it comes from

The RFC and both docs pages are silent on whether the two coexist. The Cloud
Controller presenter answers it — app/presenters/system_environment/system_env_presenter.rb
returns early:

return { SERVICE_BINDING_ROOT: '/etc/cf-service-bindings' } if @service_binding_k8s_enabled
return { VCAP_SERVICES_FILE_PATH: '/etc/cf-service-bindings/vcap_services' }
  if @file_based_vcap_services_enabled

It never reaches the code that populates VCAP_SERVICES. The two are mutually
exclusive by construction, so the file winning here only decides the tie in a
synthetic environment.

Decisions

  • An unreadable file is an error, not a fallback. On a file-based app
    VCAP_SERVICES is unset, so falling back would hand the caller an app with
    no services and no explanation. The error names the variable and wraps the
    underlying cause.
  • SERVICE_BINDING_ROOT is out of scope, as the reporter argued: those
    bindings follow the servicebinding.io layout, which has no faithful
    translation into VCAP_SERVICES shape.
  • go.mod is untouched. The go directive floor bump is deliberately not
    bundled here.

On the gosec annotation

Reading a platform-supplied path is the entire feature, so the path is
necessarily a variable and gosec's G304 fires. The #nosec G304 is scoped to
that single line with the reason in a comment. Verified it is load-bearing —
removing it reproduces:

G304 (CWE-22): Potential file inclusion via variable (Confidence: HIGH, Severity: MEDIUM)

API impact

gorelease reports no exported API change: the helper is unexported and this
is behavior only. Backward-compatible new functionality, so v1.22.0.

Verification

  • make check clean, make test-race passes, make gosec clean
  • coverage 91.0% -> 93.6%
  • tests cover: reading from the file when VCAP_SERVICES is absent, the file
    winning when both are set, a hard error on an unreadable file, malformed JSON
    in the file, and the unchanged VCAP_SERVICES path

Also carries the changelog.d sweep for the fragment v1.21.0 consumed.

With the file-based-vcap-services app feature enabled, Cloud Foundry
sets VCAP_SERVICES_FILE_PATH and does not set VCAP_SERVICES at all, so
New unmarshalled an empty string and every such app failed outright.
The feature exists because bindings can exceed the environment variable
size limit (RFC-0030).

The file wins when both are set. Cloud Foundry never sets both, so this
only decides the tie in a synthetic environment.

An unreadable file is an error rather than a fall back to VCAP_SERVICES:
on a file-based app that variable is unset, so falling back would hand
the caller an app with no services and no explanation.

The K8s service-binding form of the RFC is deliberately not implemented.
It cannot be translated into VCAP_SERVICES shape.

Closes #28
@norman-abramovitz
norman-abramovitz merged commit 19086d2 into master Jul 28, 2026
6 checks passed
@norman-abramovitz
norman-abramovitz deleted the file-based-service-bindings branch July 29, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for file based service bindings

1 participant