ServerOptions.Credentials does two unrelated jobs, and there is no way to ask for one without the other.
What is coupled
In Server.ServeHTTP the registry is what maps an access key to an account (emulator/server.go, step 1.5):
if s.opts.Credentials != nil {
if entry, ok := s.opts.Credentials.Lookup(accessKey); ok {
reqCtx.AccountID = entry.AccountID
registryHit = true
}
}
and immediately after, step 1.6 runs SigV4 verification gated on the same field being non-nil. An access key the registry does not know is then InvalidClientTokenId 403 (emulator/credentials.go, VerifySigV4).
So Credentials non-nil means two things at once: "resolve accounts from this table" and "enforce signatures on every request". The resolvePrincipal doc comment already notes the coupling; this issue is about removing it.
Why it matters
StartTestServer (emulator/testing.go) does not wire a registry, so every in-repo test authenticates as either 123456789012 (any AKIA… key) or 000000000000 (anything else) via extractAccount in emulator/parser.go. A test that needs to be a third account — or a specific vended member account — has no route.
Wiring a registry into StartTestServer to fix that would switch signature verification on for the whole repository in one step, since the two are the same flag. That is a repository-wide behaviour change, and it does not belong inside whatever feature happens to need multi-account tests.
Where this came from
#623 needs to authenticate as a vended member account. It works around this by adding a separate opt-in entry point (StartTestServerWithAccounts) that wires its own registry, leaving StartTestServer untouched. That is the right call for one feature but it is a second door, not a fix: the repository ends up with two test servers whose auth behaviour differs, and the difference is not the one a reader would guess from the names.
What it would take
Give signature verification its own ServerOptions field, so the four combinations are all expressible:
| Credentials |
Verify signatures |
Meaning |
| nil |
off |
today's StartTestServer — keys map by prefix heuristic |
| set |
off |
the missing one — real multi-account identity, unsigned requests fine |
| set |
on |
today's behaviour when Credentials is set |
| nil |
on |
nothing to verify against; must be rejected at construction |
Then StartTestServer can wire a registry for everyone, StartTestServerWithAccounts collapses into it, and a test that wants signature enforcement asks for it explicitly.
The last row is the one to get right: Verify: true with no registry has no key material to check against, so it should be a construction-time error rather than a server that 403s everything.
Acceptance criteria
ServerOptions.Credentialsdoes two unrelated jobs, and there is no way to ask for one without the other.What is coupled
In
Server.ServeHTTPthe registry is what maps an access key to an account (emulator/server.go, step 1.5):and immediately after, step 1.6 runs SigV4 verification gated on the same field being non-nil. An access key the registry does not know is then
InvalidClientTokenId403 (emulator/credentials.go,VerifySigV4).So
Credentialsnon-nil means two things at once: "resolve accounts from this table" and "enforce signatures on every request". TheresolvePrincipaldoc comment already notes the coupling; this issue is about removing it.Why it matters
StartTestServer(emulator/testing.go) does not wire a registry, so every in-repo test authenticates as either123456789012(anyAKIA…key) or000000000000(anything else) viaextractAccountinemulator/parser.go. A test that needs to be a third account — or a specific vended member account — has no route.Wiring a registry into
StartTestServerto fix that would switch signature verification on for the whole repository in one step, since the two are the same flag. That is a repository-wide behaviour change, and it does not belong inside whatever feature happens to need multi-account tests.Where this came from
#623 needs to authenticate as a vended member account. It works around this by adding a separate opt-in entry point (
StartTestServerWithAccounts) that wires its own registry, leavingStartTestServeruntouched. That is the right call for one feature but it is a second door, not a fix: the repository ends up with two test servers whose auth behaviour differs, and the difference is not the one a reader would guess from the names.What it would take
Give signature verification its own
ServerOptionsfield, so the four combinations are all expressible:StartTestServer— keys map by prefix heuristicCredentialsis setThen
StartTestServercan wire a registry for everyone,StartTestServerWithAccountscollapses into it, and a test that wants signature enforcement asks for it explicitly.The last row is the one to get right:
Verify: truewith no registry has no key material to check against, so it should be a construction-time error rather than a server that 403s everything.Acceptance criteria
ServerOptionsfield, independent ofCredentialsVerifywithoutCredentialsis refused at construction, not at request timeStartTestServerwires aCredentialRegistrywith verification off; no existing test changes behaviourStartTestServerWithAccountsis folded back intoStartTestServer(or kept as a thin wrapper), so there is one test server whose auth behaviour is described in one placeset/offcombination: a registered key resolves to its account, and an unsigned request with that key is not a 403set/oncombination still 403s an unregistered key withInvalidClientTokenId