One-view tokens: local records in linked zones, zone lookup, view list
A token for one view of a linked zone (an ACME token for external) couldn't add records: a new record was shared and reached the other view. A new name and type is now local when the user may not change it in the other views. A zone name in several views resolves to the only one the user can see, and the error no longer names views they can't. GET /views lists the views a user sees zones in (name, colour, count; limited) without views:read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4cc2ab2287
commit
57012fece8
13 files changed
+159
-12
No files matched your search
@@ -413,3 +413,37 @@ func TestDeleteLocalOverride(t *testing.T) {
|
||||
t.Errorf("validation: %+v", probs)
|
||||
}
|
||||
}
|
||||
|
||||
// An ACME token for one view of a linked zone: its challenge records are
|
||||
// local to that view, the zone is found without naming the view, and they
|
||||
// go again without touching the other view.
|
||||
func TestLinkedACMEToken(t *testing.T) {
|
||||
env := linkedEnv(t)
|
||||
env.submit(env.admin, NewRequest(OpZoneCreate, 0, ZoneInput{Name: model.Ptr("example.com"), View: model.Ptr("external"), LinkWith: "internal"}))
|
||||
u := &model.User{Username: "certbot", Grants: []model.Grant{{Resource: auth.ResRecords, Access: "write", Zones: []string{"example.com"}, Views: []string{"external"}, Names: []string{"_acme-challenge.*"}, Types: []string{"TXT"}}}}
|
||||
if err := env.st.CreateUser(env.ctx, u); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bot := &auth.Principal{User: u, Method: "token"}
|
||||
name, typ, data := "_acme-challenge", "TXT", "token-value"
|
||||
res := env.submit(bot, NewRequest(OpRecordCreate, 0, RecordInput{Zone: "example.com", Name: &name, Type: &typ, Data: &data}))
|
||||
if !slices.Contains(env.view("external"), "_acme-challenge TXT \"token-value\" L") || slices.ContainsFunc(env.view("internal"), func(s string) bool { return strings.HasPrefix(s, "_acme-challenge") }) {
|
||||
t.Errorf("challenge: internal %q external %q", env.view("internal"), env.view("external"))
|
||||
}
|
||||
if !slices.ContainsFunc(res.Warnings, func(w string) bool { return strings.Contains(w, "local to view external") }) {
|
||||
t.Errorf("warnings %q", res.Warnings)
|
||||
}
|
||||
env.submit(bot, NewRequest(OpRecordDelete, 0, RecordInput{Zone: "example.com", Name: &name, Type: &typ, Data: &data}))
|
||||
if slices.ContainsFunc(env.view("external"), func(s string) bool { return strings.HasPrefix(s, "_acme-challenge") }) {
|
||||
t.Errorf("not deleted: %q", env.view("external"))
|
||||
}
|
||||
// The admin, who may change both, still gets a shared record.
|
||||
env.submit(env.admin, NewRequest(OpRecordCreate, 0, RecordInput{Zone: "example.com", View: "internal", Name: model.Ptr("both"), Type: model.Ptr("A"), Data: model.Ptr("192.0.2.7")}))
|
||||
if !slices.Contains(env.view("external"), "both A 192.0.2.7 S") {
|
||||
t.Errorf("admin: %q", env.view("external"))
|
||||
}
|
||||
// Without a view, the admin is still asked which.
|
||||
if e := env.submitErr(env.admin, NewRequest(OpRecordCreate, 0, RecordInput{Zone: "example.com", Name: model.Ptr("x"), Type: model.Ptr("A"), Data: model.Ptr("192.0.2.8")})); !strings.Contains(e.Message, "several views (internal, external)") {
|
||||
t.Errorf("admin without a view: %v", e)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user