Skip to content

Commit

Permalink
HGWGDC-21161: Logging of unauthorised requests (#8)
Browse files Browse the repository at this point in the history
* HGWGDC-21161: Logging of unauthorised requests.

* HGWGDC-21161: Refactor config and initialize the config in main.go
  • Loading branch information
chaitanyasingla-dt authored Oct 17, 2023
1 parent e20e3c9 commit 0489daf
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
5 changes: 5 additions & 0 deletions forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func forwarder(c echo.Context, client *http.Client) error {
req := c.Request()
ctx := req.Context()

if isAuthHeaderCheckEnabled && len(c.Request().Header.Get("Authorization")) == 0 {
log.Ctx(ctx).Error().Msg("authorization header not provided")
return c.JSON(http.StatusBadRequest, echo.NewHTTPError(http.StatusBadRequest, "authorization header not provided"))
}

// store scheme of original request
originalRequestScheme := req.URL.Scheme
if originalRequestScheme == "" {
Expand Down
5 changes: 5 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ var (
sentryEnabled = false
remoteUpdateAddressEnabled = false
resourceURL *url.URL
isAuthHeaderCheckEnabled = false
authHeaderCheckRequestPath = ""
)

var rootCmd = &cobra.Command{
Expand All @@ -62,6 +64,9 @@ var rootCmd = &cobra.Command{
printConfig()
logging(viper.Sub("log"))

isAuthHeaderCheckEnabled = viper.GetBool("server.authHeader.check.enabled")
authHeaderCheckRequestPath = viper.GetString("server.authHeader.check.requestPath")

var err error
petasosURL, err = url.Parse(viper.GetString(petasosEndpoint))
if err != nil {
Expand Down
53 changes: 48 additions & 5 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"strconv"
"time"

"strings"

"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/prometheus/client_golang/prometheus"
Expand All @@ -14,8 +16,10 @@ import (
var labelNames = []string{"code", "method", "host", "url"}

type metricRegistry struct {
TotalRequests *prometheus.CounterVec
ServerRequestDuration *prometheus.HistogramVec
TotalRequests *prometheus.CounterVec
ServerRequestDuration *prometheus.HistogramVec
RequestsWithoutAuthHeader *prometheus.CounterVec
RequestsWithAuthHeader *prometheus.CounterVec
}

func provideMetrics(e *echo.Echo) {
Expand All @@ -31,6 +35,12 @@ func provideMetrics(e *echo.Echo) {
if err := prometheus.Register(mr.ServerRequestDuration); err != nil {
metrics.Logger.Fatal(err)
}
if err := prometheus.Register(mr.RequestsWithoutAuthHeader); err != nil {
metrics.Logger.Fatal(err)
}
if err := prometheus.Register(mr.RequestsWithAuthHeader); err != nil {
metrics.Logger.Fatal(err)
}

metrics.Use(mr.getMiddleware())
metrics.GET("/metrics", echo.WrapHandler(promhttp.Handler()))
Expand Down Expand Up @@ -73,17 +83,42 @@ func registerMetrics() *metricRegistry {
labelNames,
)

requestsWithoutAuthHeader := prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: "server_request_without_auth_header_count",
Help: "total requests without authorization header",
},
labelNames,
)

requestsWithAuthHeader := prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: "server_request_with_auth_header_count",
Help: "total requests with authorization header",
},
labelNames,
)

return &metricRegistry{
TotalRequests: totalRequests,
ServerRequestDuration: serverRequestDuration,
TotalRequests: totalRequests,
ServerRequestDuration: serverRequestDuration,
RequestsWithoutAuthHeader: requestsWithoutAuthHeader,
RequestsWithAuthHeader: requestsWithAuthHeader,
}
}

func (mr *metricRegistry) getMiddleware() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
startTime := time.Now()
isCpeRedirectRequest := strings.Contains(c.Request().RequestURI, authHeaderCheckRequestPath)
isAuthHeaderPresent := len(c.Request().Header.Get("Authorization")) > 0
c.Request().Header.Set("Accept-Encoding", "identity")

startTime := time.Now()
err := next(c)
elapsed := time.Since(startTime).Seconds()
status := strconv.Itoa(c.Response().Status)
Expand All @@ -96,6 +131,14 @@ func (mr *metricRegistry) getMiddleware() echo.MiddlewareFunc {

mr.TotalRequests.WithLabelValues(values...).Inc()
mr.ServerRequestDuration.WithLabelValues(values...).Observe(elapsed)

if isCpeRedirectRequest {
if !isAuthHeaderPresent {
mr.RequestsWithoutAuthHeader.WithLabelValues(values...).Inc()
} else {
mr.RequestsWithAuthHeader.WithLabelValues(values...).Inc()
}
}
return err
}
}
Expand Down
8 changes: 8 additions & 0 deletions petasos-rewriter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ server:
# If set, all redirects will use this scheme [http, https]
fixedScheme:

# Verify the presence of the Authorization header in requests that are redirected to Talaria
authHeader:
check:
# If enabled, the request will be rejected if the Authorization header is not present
enabled: true
# The request path where the presence of the Authorization header is to be checked
requestPath: api

#Petasos endpoint, usually private
petasos:
endpoint: http://192.168.100.128:6400
Expand Down

0 comments on commit 0489daf

Please sign in to comment.