feat: add OAuth2 password grant support for event generator log-cache access - #1265
Conversation
… 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
| } | ||
|
|
||
| func (c UAACreds) IsNotEmpty() bool { | ||
| return c.URL != "" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
| 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"` |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
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
|



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 configurationcf/cfclient_wrapper.go: Support password grant in CF client wrappermodels/uaa_creds.go: New UaaCreds model for password grant configeventgenerator/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 factoryTesting
Part 1 of 4 — Split from #1149 for easier review.