You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add OAuth2 password grant support for event generator log-cache access (#1265)
* feat: add OAuth2 password grant support for event generator log-cache 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
* refactor: simplify oauth2 password grant code
- 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
* fix: resolve reviewdog CI failure
- Remove extra blank line at cf/cfclient_wrapper_test.go:281 that caused gofmt formatting violation
* fix: validate cached token in race condition path
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.
* fix: remove sensitive data from token error messages
UAA error responses may contain access tokens, client IDs, or other
sensitive information. Only log the HTTP status code, not the response body.
* docs: add UAA password grant fields to eventgenerator default config
Adds uaa section with grant_type, username, and password fields for
discoverability. Shows the available configuration options without
requiring code inspection.
* fix: prevent negative token expiry for short-lived tokens
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.
* docs: add eventgenerator README with password grant documentation
Documents both client_credentials and password grant authentication
modes for Log Cache access, including example configs and field
descriptions.
* refactor: harden OAuth2 client based on review feedback
- 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
* fix: pass logger to NewCFOauth2HTTPClient in fetcher_factory_test
* chore: update devbox.lock plugin versions to 0.0.5
* fix: resolve unit test failures
- 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
The Event Generator polls metrics from CF Log Cache, aggregates them, evaluates scaling rules, and triggers scaling events when thresholds are breached.
4
+
5
+
## Log Cache Authentication
6
+
7
+
The Event Generator needs to authenticate with CF's Log Cache to read application metrics. Two authentication modes are supported:
8
+
9
+
### Client Credentials (default)
10
+
11
+
Uses a UAA client with `client_credentials` grant. The client needs the `logs.admin` authority. This mode uses the standard go-log-cache OAuth2 client internally.
12
+
13
+
```yaml
14
+
uaa:
15
+
url: https://uaa.sys.example.com
16
+
client_id: autoscaler_client
17
+
client_secret: my-secret
18
+
skip_ssl_validation: false
19
+
```
20
+
21
+
### Password Grant
22
+
23
+
Uses the `password` grant type with CF user credentials. This is useful when a dedicated UAA client with `logs.admin` is not available — instead, an org manager user with Log Cache access can be used.
24
+
25
+
The default client ID is `cf` (CF's built-in public UAA client with an empty secret), matching `cf login` behavior.
26
+
27
+
```yaml
28
+
uaa:
29
+
url: https://uaa.sys.example.com
30
+
client_id: cf
31
+
client_secret: ""
32
+
grant_type: password
33
+
username: org-manager@example.com
34
+
password: my-password
35
+
skip_ssl_validation: false
36
+
```
37
+
38
+
**Required fields for password grant:**
39
+
- `url`— UAA base URL (e.g., `https://uaa.sys.example.com`); `/oauth/token` is appended automatically
40
+
- `grant_type`— must be `password`
41
+
- `username`— CF user with access to app metrics via Log Cache
42
+
- `password`— user password
43
+
44
+
**Optional fields:**
45
+
- `client_id`— defaults to `cf` if empty
46
+
- `client_secret`— empty for the `cf` client (public client)
47
+
- `skip_ssl_validation`— defaults to `false`
48
+
49
+
### How it works
50
+
51
+
The password grant OAuth2 client:
52
+
1. Authenticates using HTTP Basic auth header (`client_id:client_secret`) with username/password in the request body
53
+
2. Caches the access token until shortly before expiry (30-second buffer, or half the token lifetime for short-lived tokens)
54
+
3. Automatically refreshes on 401 responses with stale-token detection under lock to prevent thundering herd
55
+
4. Retries once after a forced token refresh
56
+
57
+
## Configuration
58
+
59
+
See [`default_config.json`](./default_config.json) for all available configuration options.
0 commit comments