Skip to content

Commit

Permalink
OTT-1682 : Add security headers in response (#840)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ankit-Pinge authored Jul 9, 2024
1 parent 57a06ba commit 36a9c63
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 1 deletion.
22 changes: 22 additions & 0 deletions modules/pubmatic/openwrap/http_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package openwrap

import (
"net/http"

"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
)

// Middleware to set headers for responses
func SetResponseHeaders(serverHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Set response headers
SetSecurityHeaders(w)
serverHandler.ServeHTTP(w, r)
})
}

func SetSecurityHeaders(rw http.ResponseWriter) {
rw.Header().Set("Content-Security-Policy", models.ContentSecurityPolicy)
rw.Header().Set("X-Content-Type-Options", models.XContentTypeOptions)
rw.Header().Set("X-XSS-Protection", models.XXSSProtection)
}
93 changes: 93 additions & 0 deletions modules/pubmatic/openwrap/http_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package openwrap

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/prebid/prebid-server/v2/modules/pubmatic/openwrap/models"
"github.com/stretchr/testify/assert"
)

func TestSetSecurityHeaders(t *testing.T) {
type args struct {
rw http.ResponseWriter
}
tests := []struct {
name string
args args
want http.Header
}{
{
name: "valid security headers",
args: args{
&httptest.ResponseRecorder{},
},
want: http.Header{
"X-Content-Type-Options": []string{models.XContentTypeOptions},
"X-Xss-Protection": []string{models.XXSSProtection},
"Content-Security-Policy": []string{models.ContentSecurityPolicy},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetSecurityHeaders(tt.args.rw)
assert.Equal(t, tt.want, tt.args.rw.Header())
})
}
}

func TestSetResponseHeaders(t *testing.T) {
type args struct {
serverHandler http.Handler
}
tests := []struct {
name string
args args
expectedStatus int
expectedBody string
expectedHeaders map[string]string
}{
{
name: "valid headers",
args: args{
serverHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}),
},
expectedStatus: http.StatusOK,
expectedBody: "OK",
expectedHeaders: map[string]string{
"Content-Security-Policy": models.ContentSecurityPolicy,
"X-Content-Type-Options": models.XContentTypeOptions,
"X-XSS-Protection": models.XXSSProtection,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handler := SetResponseHeaders(tt.args.serverHandler)
req := httptest.NewRequest(http.MethodGet, "/", nil)
rr := httptest.NewRecorder()

handler.ServeHTTP(rr, req)

if status := rr.Code; status != tt.expectedStatus {
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.expectedStatus)
}

if rr.Body.String() != tt.expectedBody {
t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), tt.expectedBody)
}

// Check the response headers
for key, value := range tt.expectedHeaders {
if rr.Header().Get(key) != value {
t.Errorf("header %v = %v, want %v", key, rr.Header().Get(key), value)
}
}
})
}
}
6 changes: 6 additions & 0 deletions modules/pubmatic/openwrap/models/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,9 @@ const (
MissingSignal = "missing"
InvalidSignal = "invalid"
)

const (
ContentSecurityPolicy = "frame-ancestors 'self' https://pubmatic.com https://*.pubmatic.com"
XContentTypeOptions = "nosniff"
XXSSProtection = "1; mode=block"
)
2 changes: 1 addition & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func newAdminServer(cfg *config.Configuration, handler http.Handler) *http.Serve

func newMainServer(cfg *config.Configuration, handler http.Handler) *http.Server {
serverHandler := getCompressionEnabledHandler(handler, cfg.Compression.Response)

serverHandler = openwrap.SetResponseHeaders(serverHandler)
return &http.Server{
Addr: cfg.Host + ":" + strconv.Itoa(cfg.Port),
Handler: serverHandler,
Expand Down

0 comments on commit 36a9c63

Please sign in to comment.