feat: bypass security for health checks and support HEAD downloads
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 2m30s
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 2m30s
- Allow the `/health` endpoint to bypass the security middleware, ensuring container health checks succeed even if the proxy IP is banned. - Add a test to verify health checks from banned IPs. - Register a HEAD route for file downloads. - Refactor admin alert status checks to use a new `isUnacknowledgedAlert` helper. - Update the security runbook documentation with clearer instructions and examples for trusted proxy configuration.
This commit is contained in:
@@ -4,8 +4,10 @@ import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -233,7 +235,8 @@ func (app *App) handleDownloadFile(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
ctx.String(http.StatusNotFound, "File not found")
|
||||
return
|
||||
}
|
||||
@@ -242,12 +245,49 @@ func (app *App) handleDownloadFile(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.FileAttachment(path, filename)
|
||||
if !app.serveDownloadFile(ctx, path, filename, info) {
|
||||
return
|
||||
}
|
||||
if hasManifest && app.config.RenewOnDownloadEnabled {
|
||||
boxstore.RenewManifest(boxID, manifest.RetentionSecs)
|
||||
}
|
||||
}
|
||||
|
||||
func (app *App) serveDownloadFile(ctx *gin.Context, path string, filename string, info os.FileInfo) bool {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
ctx.String(http.StatusInternalServerError, "Could not read file")
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
mimeType := helpers.MimeTypeForFile(path, filename)
|
||||
ctx.Header("Content-Type", mimeType)
|
||||
ctx.Header("Content-Disposition", contentDispositionForDownload(filename, mimeType))
|
||||
ctx.Header("X-Content-Type-Options", "nosniff")
|
||||
http.ServeContent(ctx.Writer, ctx.Request, filename, info.ModTime(), file)
|
||||
return true
|
||||
}
|
||||
|
||||
func contentDispositionForDownload(filename string, mimeType string) string {
|
||||
disposition := "attachment"
|
||||
if isEmbeddableMimeType(mimeType) {
|
||||
disposition = "inline"
|
||||
}
|
||||
return mime.FormatMediaType(disposition, map[string]string{"filename": filename})
|
||||
}
|
||||
|
||||
func isEmbeddableMimeType(mimeType string) bool {
|
||||
baseType := strings.ToLower(strings.TrimSpace(strings.Split(mimeType, ";")[0]))
|
||||
if strings.HasPrefix(baseType, "video/") || strings.HasPrefix(baseType, "audio/") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(baseType, "image/") {
|
||||
return baseType != "image/svg+xml"
|
||||
}
|
||||
return baseType == "application/pdf" || baseType == "text/plain"
|
||||
}
|
||||
|
||||
func (app *App) handleDownloadThumbnail(ctx *gin.Context) {
|
||||
boxID := ctx.Param("id")
|
||||
fileID := ctx.Param("file_id")
|
||||
|
||||
Reference in New Issue
Block a user