Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cmd/image/cdn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,19 @@ func TestUpdateCDN(t *testing.T) {
if got := get("/testing/construct_20261004.2.efi"); got != "kernel 20261004.2" || c.redirects.Load() != 1 {
t.Errorf("the kernel image through the redirect: %q, %d redirects", got, c.redirects.Load())
}
// Only what an index lists is a file: a version no release has, a file in another release's
// slot, a release directory's other files, and a path out of it are all nothing.
for _, p := range []string{"/testing/construct_20261004.3.efi", "/assets/v1/construct_20261004.2.efi", "/assets/v2/SHA256SUMS", "/assets/v2/../release.pem"} {
resp, err := http.Get(base + p)
if err != nil {
t.Fatal(err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusNotFound {
t.Errorf("%s: %s, not 404", p, resp.Status)
}
}
if c.redirects.Load() != 1 {
t.Errorf("%d redirects after the refused requests, not 1", c.redirects.Load())
}
}
30 changes: 17 additions & 13 deletions cmd/image/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,9 @@ func newUpdateCDN(dir string, versions map[string]string, keyRef, pubring string
if err := os.RemoveAll(root); err != nil {
return nil, err
}
byVersion := map[string]string{}
// What is served is what the indexes list and nothing else, each file by the name a request
// gives, to a path made here from the index's line: a request's text never reaches the disk.
slots, files := map[string]string{}, map[string]string{}
for ch, vs := range map[string][]string{"stable": {"v1"}, "testing": {"v1", "v2"}} {
idx := index{}
for _, v := range vs {
Expand All @@ -508,7 +510,11 @@ func newUpdateCDN(dir string, versions map[string]string, keyRef, pubring string
return nil, err
}
idx[versions[v]] = rel[versions[v]]
byVersion[versions[v]] = v
for _, line := range rel[versions[v]] {
name := strings.Fields(line)[1]
slots[name] = v
files[name] = filepath.Join(dir, v+".release", name)
}
}
sums := filepath.Join(root, ch, "SHA256SUMS")
if err := os.MkdirAll(filepath.Dir(sums), 0o755); err != nil {
Expand All @@ -522,23 +528,21 @@ func newUpdateCDN(dir string, versions map[string]string, keyRef, pubring string
}
}
c := &updateCDN{}
files := http.FileServer(http.Dir(root))
indexes := http.FileServer(http.Dir(root))
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/"), "/")
if len(parts) == 2 {
if m := releaseFile.FindStringSubmatch(parts[1]); m != nil {
if v, ok := byVersion[m[1]]; ok && parts[0] != "assets" {
c.redirects.Add(1)
http.Redirect(w, r, "/assets/"+v+"/"+parts[1], http.StatusFound)
return
}
if len(parts) == 2 && parts[0] != "assets" {
if slot, ok := slots[parts[1]]; ok {
c.redirects.Add(1)
http.Redirect(w, r, "/assets/"+slot+"/"+parts[1], http.StatusFound)
return
}
}
if len(parts) == 3 && parts[0] == "assets" && releaseFile.MatchString(parts[2]) && (parts[1] == "v1" || parts[1] == "v2") {
http.ServeFile(w, r, filepath.Join(dir, parts[1]+".release", parts[2]))
if len(parts) == 3 && parts[0] == "assets" && slots[parts[2]] == parts[1] {
http.ServeFile(w, r, files[parts[2]])
return
}
files.ServeHTTP(w, r)
indexes.ServeHTTP(w, r)
})
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
Expand Down
Loading