From bd455f1782f1a72af5cd180a569a352d924c6c94 Mon Sep 17 00:00:00 2001 From: Christian Galo Date: Sun, 20 Apr 2025 01:29:13 -0500 Subject: [PATCH] Add MaxBodySize middleware and update .gitignore for config files --- .gitignore | 5 ++++- README.md | 1 + cmd/start.go | 1 + internal/middleware/security.go | 26 ++++++++++++++++++++++++++ site/sample.member-console.yaml | 13 +++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 site/sample.member-console.yaml diff --git a/.gitignore b/.gitignore index 7f00355..0c85462 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,7 @@ go.work tmp/* # Ignore the build -member-console \ No newline at end of file +member-console + +# Ignore config files +site/member-console.yaml \ No newline at end of file diff --git a/README.md b/README.md index eb89c2c..3ed2ef4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Member console application for users to create, acccess, and manage their accoun - [ ] Implement backchannel logout - [ ] Implement CSRF tokens - [ ] Make sure viper's 'env' key will work correctly in production +- [ ] Should session-secret be generated on startup instead of in the config file? --- diff --git a/cmd/start.go b/cmd/start.go index 61819ed..0d7765e 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -38,6 +38,7 @@ var startCmd = &cobra.Command{ stack := middleware.CreateStack( middleware.SecureHeaders, middleware.Logging, + middleware.MaxBodySize(1024*1024), // 1MB size limit authConfig.Middleware(), ) diff --git a/internal/middleware/security.go b/internal/middleware/security.go index 52030a7..4c15550 100644 --- a/internal/middleware/security.go +++ b/internal/middleware/security.go @@ -49,3 +49,29 @@ func CSRFMiddleware(store sessions.Store) Middleware { }) } } + +// MaxBodySize limits the maximum size of request bodies +// size parameter is in bytes +func MaxBodySize(maxSize int64) Middleware { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Skip restricting GET, HEAD, and OPTIONS requests as they shouldn't have bodies + if r.Method == http.MethodGet || r.Method == http.MethodHead || r.Method == http.MethodOptions { + next.ServeHTTP(w, r) + return + } + + // Check Content-Length header first for efficiency + if r.ContentLength > maxSize { + http.Error(w, "Request body too large", http.StatusRequestEntityTooLarge) + return + } + + // If Content-Length is not set or potentially spoofed, use LimitReader + r.Body = http.MaxBytesReader(w, r.Body, maxSize) + + // Continue to next middleware/handler + next.ServeHTTP(w, r) + }) + } +} diff --git a/site/sample.member-console.yaml b/site/sample.member-console.yaml new file mode 100644 index 0000000..b1d9964 --- /dev/null +++ b/site/sample.member-console.yaml @@ -0,0 +1,13 @@ +# WARNING - DO NOT USE THIS IN PRODUCTION +# This is a local development configuration file +# It is used to configure the member console application +# to connect to the local Keycloak server +# This file is not secure and should not be used in production +# It is only used for local development purposes only + +port: 8081 +client-id: "member-console" +client-secret: "" +issuer-url: "http://localhost:8080/realms/master" +hostname: "http://localhost:8081" +session-secret: "" \ No newline at end of file