Skip to content

feat: add OAuth2 password grant support for event generator log-cache access - #1265

Merged
bonzofenix merged 13 commits into
mainfrom
split/oauth2-password-grant
Jun 24, 2026
Merged

feat: add OAuth2 password grant support for event generator log-cache access#1265
bonzofenix merged 13 commits into
mainfrom
split/oauth2-password-grant

Conversation

@bonzofenix

@bonzofenix bonzofenix commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds OAuth2 resource owner password grant support to the CF client and event generator, enabling log-cache access via user credentials instead of client credentials.

Changes

  • cf/config.go: Add password grant fields to CF client configuration
  • cf/cfclient_wrapper.go: Support password grant in CF client wrapper
  • models/uaa_creds.go: New UaaCreds model for password grant config
  • eventgenerator/metric/cf_oauth2_client.go: New OAuth2 token client with thundering-herd prevention (sync.Once)
  • eventgenerator/metric/fetcher_factory.go: Wire password grant into fetcher factory

Testing

  • Full unit test coverage for cf_oauth2_client (490 lines)
  • Updated fetcher_factory tests
  • Updated CF config tests

Part 1 of 4 — Split from #1149 for easier review.

  1. This PR — OAuth2 password grant (code)
  2. feat: add OrgManager user support to acceptance test framework #1266 — Acceptance test OrgManager support (test framework)
  3. feat: support shared org and space-scoped broker for PR deployments #1267 — Deployment scripts: shared org + space-scoped broker
  4. ci: wire shared org deployment into CI/CD workflows #1268 — CI/CD workflows wiring

… access

- Add password grant support to CF client configuration
- New cf_oauth2_client for event generator to authenticate via resource owner password grant
- Prevent thundering herd in token refresh with sync.Once pattern
- Update fetcher factory to support password grant credentials
- Add UaaCreds model for password grant configuration
- Inline validateAPI() into Validate() — single call site, no reuse benefit
- Precompute tokenURL and basicAuthHeader in CFOauth2HTTPClient constructor
- Use models.GrantTypePassword constant instead of hardcoded "password" string
- Add missing tests: UAACreds.IsPasswordGrant and introspect Basic auth header
- Remove extra blank line at cf/cfclient_wrapper_test.go:281 that caused gofmt formatting violation
Comment thread eventgenerator/metric/cf_oauth2_client.go
Comment thread cf/config.go
Comment thread models/uaa_creds.go
}

func (c UAACreds) IsNotEmpty() bool {
return c.URL != ""

@asalan316 asalan316 Jun 23, 2026

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.

Is checking url enough ?

How about validation other fields e.g ClientID required, ClientSecret required, Username/Password ?

they seems to be required here https://github.com/cloudfoundry/app-autoscaler/pull/1265/changes#diff-ddbe55f48c292903fb81e776d43f3fc7c7c1f70f3821626bc6f85c4cffbf4b59R36

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Keeping this as-is. IsNotEmpty() is a presence check ("are UAA creds configured at all?"), not a validity check. Callers use it to branch between "UAA configured" vs "skip UAA".

Full field validation (ClientID, Username, Password, etc.) happens in cf/config.go#validatePasswordGrant() and validateClientCredentials() — separate concern from the zero-value check here.

Comment thread eventgenerator/metric/cf_oauth2_client.go Outdated
Comment thread models/uaa_creds.go
URL string `yaml:"url" json:"url"`
ClientID string `yaml:"client_id" json:"clientID"`
ClientSecret string `yaml:"client_secret" json:"clientSecret"`
GrantType string `yaml:"grant_type" json:"grantType"`

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.

hard to find new configuration without reading code . Should these new fields

 (grant_type, username, password

be placed in the default_config.json files e.g

api/default_config.json
eventgenerator/default_config.json
operator/default_config.json
scalingengine/default_config.json

@bonzofenix bonzofenix Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in d0051363e. Added UAA section to eventgenerator/default_config.json with all password grant fields.

Only added to eventgenerator since that's the only component using password grant. The other services (api, operator, scalingengine) use client_credentials and their existing configs already cover that.

Comment thread models/uaa_creds.go
Comment thread eventgenerator/metric/cf_oauth2_client.go Outdated
bonzofenix and others added 10 commits June 24, 2026 09:13
In forceRefreshToken, when another goroutine has already changed the token,
validate it (non-empty and not expired) before returning. If invalid, refresh
instead of returning a potentially stale/empty token.
UAA error responses may contain access tokens, client IDs, or other
sensitive information. Only log the HTTP status code, not the response body.
Adds uaa section with grant_type, username, and password fields for
discoverability. Shows the available configuration options without
requiring code inspection.
When expires_in <= 30, subtracting the 30s buffer creates a negative
duration causing immediate re-fetch loops. Now uses half the token
lifetime as buffer for short-lived tokens instead.
Documents both client_credentials and password grant authentication
modes for Log Cache access, including example configs and field
descriptions.
- Validate empty access_token and invalid expires_in from token response
- Add lager.Logger for observability (token refresh, 401, race condition)
- Parse UAA error/error_description in failure responses (non-sensitive)
- Wrap retry error with context
- Add startup validation for password grant credentials
- Fix README inaccuracies (CAS→mutex, buffer logic, URL field)
- Default config uses empty grant_type to avoid accidental activation
- fetcher_factory_test: avoid deep-comparing logger instances, verify
  client creation through call count and non-nil assertions instead
- cf_oauth2_client_test: use expires_in=31 (effective 1s after 30s buffer)
  with 1.1s sleep to properly test token expiry refresh
@bonzofenix
bonzofenix enabled auto-merge (squash) June 24, 2026 10:06
@bonzofenix bonzofenix self-assigned this Jun 24, 2026
@bonzofenix
bonzofenix disabled auto-merge June 24, 2026 10:07
@bonzofenix
bonzofenix merged commit ef05bd7 into main Jun 24, 2026
24 checks passed
@bonzofenix
bonzofenix deleted the split/oauth2-password-grant branch June 24, 2026 10:07
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants