Phase 1.1 of the work breakdown. The finding that shaped it came before any code: **the control plane special-cases nothing.** provides, requires, contributes and grants are entirely name-agnostic, so asking for a bucket needed no change to the mesh at all — only a provider that answers. What was missing was the last step, where something on the machine turns a delivered secret into a key that works. Named `s3-bucket` by ADR 0027's test: a consumer's code is written against the S3 API, and swapping one store for another does not break it, so the coupling is to the protocol rather than the product — which is what the substrate design already said about AMQP, S3 and OCI. Proven on a real store, 7 assertions: a generated secret becomes a working key; rotation makes the new one work and the old one stop; a consumer that goes away loses its key; a key nobody here made is left alone; a manifest naming a credential that was never written is refused; an unusable bucket name is refused naming the consumer that asked. **And the one a database does not need.** One PostgreSQL server holds separate databases and the product enforces the boundary; one object store holds every bucket behind one endpoint, so a consumer being unable to reach another's is a policy somebody wrote. A policy granting arn:aws:s3:::* would pass every other test in the file, so the unit tests assert what the policy does NOT say. It drives the vendor's command line rather than an SDK: the admin API encrypts its request bodies, which is why a separate admin library exists, and pulling that in would add a system-metrics dependency tree to a repository with none in order to create a user.
69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
// A bucket name is checked here so the refusal names the module that asked.
|
|
//
|
|
// The store would refuse most of these itself, as a REST error arriving inside a provisioner log,
|
|
// with nothing saying which consumer's manifest caused it.
|
|
func TestABucketNameThatWouldNotWorkIsRefusedHere(t *testing.T) {
|
|
for _, name := range []string{
|
|
"", // nothing asked for
|
|
"ab", // too short
|
|
"-lead",
|
|
"trail-",
|
|
"Photos", // upper case: arrives lower-cased, and works until somebody looks
|
|
"my_bucket", // underscore
|
|
"a.b", // dots are legal in S3 and break TLS host matching; not worth the surprise
|
|
} {
|
|
if err := usableBucketName(name); err == nil {
|
|
t.Errorf("%q was accepted", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAnOrdinaryBucketNameIsAccepted(t *testing.T) {
|
|
for _, name := range []string{"photos", "a-b-c", "backups2026", "abc"} {
|
|
if err := usableBucketName(name); err != nil {
|
|
t.Errorf("%q was refused: %v", name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The policy a consumer gets names its own bucket and nothing else.
|
|
//
|
|
// **The half that matters is what it does not say.** A policy granting `arn:aws:s3:::*` would
|
|
// pass every test that checks a consumer can reach its own bucket, and would give every consumer
|
|
// the whole store.
|
|
func TestThePolicyGrantsOneBucketAndNoOther(t *testing.T) {
|
|
policy := onlyThatBucket("photos")
|
|
for _, want := range []string{`"arn:aws:s3:::photos"`, `"arn:aws:s3:::photos/*"`} {
|
|
if !contains(policy, want) {
|
|
t.Errorf("the policy does not carry %s:\n%s", want, policy)
|
|
}
|
|
}
|
|
for _, unwanted := range []string{`:::*`, `"*"`, `:::photos-other`} {
|
|
if contains(policy, unwanted) {
|
|
t.Errorf("the policy carries %s, which reaches beyond the bucket asked for:\n%s",
|
|
unwanted, policy)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A policy is per consumer, so one asking for a second bucket cannot widen another's.
|
|
func TestTwoConsumersGetPoliciesThatDoNotOverlap(t *testing.T) {
|
|
if contains(onlyThatBucket("photos"), "invoices") ||
|
|
contains(onlyThatBucket("invoices"), "photos") {
|
|
t.Error("a consumer's policy names another consumer's bucket")
|
|
}
|
|
}
|
|
|
|
func contains(haystack, needle string) bool {
|
|
for i := 0; i+len(needle) <= len(haystack); i++ {
|
|
if haystack[i:i+len(needle)] == needle {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|