Azure Bucket: anonymous access to public containers is unreachable since #1875
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 55/100
Research direction
Start in internal/bucket/azure/blob.go at chainCredentialWithSecret and the client-selection path, then inspect auth/azure.NewTokenCredential and the anonymous cases in blob_test.go. Run staticcheck ./internal/... and make test to confirm the control flow and existing coverage. Done means a Bucket without secretRef can reach anonymous access in production, with tests covering that path.
Written by the indexing model from the issue text.
Description
Since #1875 (04ab27b42a4ab3bc989accdd8e958e189c60370c, merged 2025-09-02), a Bucket with provider: azure and no secretRef can no longer get an unauthenticated client. Both paths that would produce one are unreachable on main (99d894dd).
Why
chainCredentialWithSecret appends a credential that is never nil:
https://github.com/fluxcd/source-controller/blob/main/internal/bucket/azure/blob.go#L518
if token := azureauth.NewTokenCredential(ctx, opts...); token != nil {
creds = append(creds, token)
}
auth/azure.NewTokenCredential returns &tokenCredential{ctx, opts} — a non-nil pointer in a non-nil interface, unconditionally. So the guard is always true, creds is never empty, len(creds) > 0 always holds, and the documented return nil, nil ("If no valid token is created, it returns nil") is dead code.
That propagates to the caller, where token != nil is then always true:
token, err = chainCredentialWithSecret(ctx, o.secret, o.authOpts...)
...
if token != nil {
c.Client, err = azblob.NewClient(obj.Spec.Endpoint, token, clientOpts)
return
}
// Fallback to simple client.
c.Client, err = azblob.NewClientWithNoCredential(obj.Spec.Endpoint, clientOpts) // unreachable
The other unauthenticated path, the o.withoutCredentials early return, is gated on an unexported withoutCredentials() option that is only ever called from blob_test.go (4 call sites) and never from production code. So the anonymous behaviour that tests exercise is reached through a door the reconciler does not have, which is why the tests still pass.
Before #1875 this worked: creds only received NewEnvironmentCredential when that returned non-nil, so an empty chain — and therefore the nil, nil return and the no-credential fallback — was reachable.
Impact
A public/anonymously-readable Azure container configured without a secretRef gets an azblob client carrying a token credential instead of a no-credential client. At request time that calls auth.GetAccessToken, which fails when no Azure identity is configured, so the fetch fails rather than falling back to anonymous access.
I have verified the control flow and the regression point by reading the source; I have not reproduced it against a live public container, so please treat the runtime symptom as inferred from the code path rather than observed.
Found by
staticcheck ./internal/... flags it as SA4023, "this comparison is always true". The repo has no .golangci.yaml and CI runs make test only, so the check does not currently run anywhere.
Possible fixes
- Drop the always-true
token != nilguard and decide the chain on whether any credential source is actually configured, sochainCredentialWithSecretcan returnnil, nilagain as documented. - Or make the intent explicit at the caller and have the reconciler pass the existing
withoutCredentials()option when nosecretRefis set, which would also give the anonymous path production coverage rather than test-only coverage.
Happy to open a PR for whichever direction you prefer.
- Dominant language
- Go
- Stars
- 283
- Forks
- 252
- Avg merge
- 1h 6m
- Merged PRs (30d)
- 12
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from fluxcd/source-controller
-
area/docs good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
fluxcd/source-controller#666 · 2 comments ·
-
area/git bug
Difficulty 4/5 3-5 days Newbie friendliness 55/100
fluxcd/source-controller#2165 · 3 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
fluxcd/source-controller#2150 ·
-
GitRepository `.spec.ref.commit` + `.spec.ref.branch` does not shallow clone, contrary to the docs Open
Difficulty 5/5 Over a week Newbie friendliness 42/100
fluxcd/source-controller#2146 · 2 comments ·
-
HelmRepository: use conditional HTTP requests (ETag / If-Modified-Since) when fetching index.yaml Open
Difficulty 4/5 3-5 days Newbie friendliness 48/100
fluxcd/source-controller#2113 · 1 comment ·
All issues in fluxcd/source-controller
Similar issues
-
area/dev-productivity area/disaster-recovery area/ipcei kind/enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
kind/bug status/0-triage
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
🤔 refinement needed
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
equinor/radix-operator#1979 ·