[Fix] IAM: Fix cross-tenant agency AK/SK auth#955
Conversation
| client.DomainID = client.AKSKAuthOptions.DomainID | ||
| } | ||
|
|
||
| client.ReauthFunc = func() error { |
There was a problem hiding this comment.
This introduces a data race: ReauthFunc rewrites client.AKSKAuthOptions while every request reads it unlocked when signing (provider_client.go:291-305).
The old code never hit this path because it cleared AccessKey. go test -race shows it right away.
There was a problem hiding this comment.
The race is real. Signing reads client.AKSKAuthOptions.* unlocked (provider_client.go:291-303), and ReauthFunc writes those same fields. reauthenticateAndRetry holds client.mut around ReauthFunc, but a first-time request signs in doRequest without taking that lock, so a concurrent sign and reauth can hit it together. The old token path avoided this by clearing AccessKey and skipping the signing block; we can't, because retries need AccessKey to re-sign.
One caveat for the thread: the suggested replacement doesn't fully close it. It swaps a whole-struct assignment for field-by-field writes, which shrinks the window, but those writes are still unlocked and still race the unlocked reads.
There is no locked setter for AK/SK options; only SetToken/Token guard anything. go test -race passes here only because the tests never sign a request while a reauth is running.
Decision: take the snippet now for the smaller window, and track the real fix separately: a locked accessor around the AK/SK signing reads and reauth writes in provider_client.go. That touches the signing path for every service, so it's out of scope for a hotfix. Pre-existing gap, not something this PR introduced. I will create a follow-up issue if you agree.
There was a problem hiding this comment.
Agreed it's real but it's not pre-existing. This PR makes it reachable (old code cleared AccessKey and signing was skipped).
I'm fine to merge it and fix in the next issue.
da8d055 to
52aa9b2
Compare
* Replace agency token flow with temporary AK/SK (assume_role) auth * Add tests for delegated-project and domain-scope paths
* Add reuseEndpointLocator to v3AKSKAuth to reuse the first pass's locator * Skip the assumed-role GET /v3/auth/catalog that returns 403 * Assert the catalog is never fetched with the temporary AK/SK in tests
* Drop reuseEndpointLocator; restore v3AKSKAuth to its original signature * Apply temporary AK/SK to the client directly instead of re-running v3AKSKAuth * Resolve delegated project or agency domain ID as the assumed identity * Return the agency-domain lookup error instead of swallowing it
52aa9b2 to
2c5a12f
Compare
2a2ffe0
into
opentelekomcloud:devel
What this PR does / why we need it
Fixes cross-tenant agency AK/SK authentication, which failed in two places. First,
authWithAgencyByAKSKused the agency token flow (tokens3.Create) and clearedclient.AKSKAuthOptions.AccessKey, leaving the client without credentials to sign with on retry. It now obtains a temporary AK/SK through the IAMassume_rolecredential flow and re-authenticates viav3AKSKAuth, sorequests stay AK/SK-signed and re-sign correctly on reauth.
credentials.CreateTemporaryv3AKSKAuthusing the temporary AK/SK and security tokenAccessKeyinstead of clearing itThe temporary-AK/SK change then exposed a second failure: the re-authentication signed
GET /v3/auth/catalogwith the assumed-role identity, which OTC returns 403 for. That second fetch is redundant — the first pass (build-user AK/SK)already built a working, region-global
EndpointLocatorfrom an identical catalog.v3AKSKAuthnow takes areuseEndpointLocatorflag; the second agency pass skips the forbidden fetch and reuses the existing locator. Plain AK/SK andthe first agency pass are unchanged.
reuseEndpointLocatortov3AKSKAuth; skip the catalog re-fetch on the assumed-role pass and reuse the first pass'sEndpointLocator/v3/auth/catalogis never fetched with thetemporary AK/SKWhich issue this PR fixes
Special notes for your reviewer
Pre-existing, out of scope: when no delegated project is given,
v3AKSKAuthswallows a failed agency-domain lookup and leavesDomainIDempty rather than erroring (openstack/client.go:300-307). A wrong agency-domain name passes auth and fails on the first call instead. Sincev3AKSKAuthis shared by all AK/SK paths, I'd fix it in the agency caller in a follow-up. Happy to pick it up.