diff --git a/adapter.go b/adapter.go index a4cd89d..f8f7a9f 100644 --- a/adapter.go +++ b/adapter.go @@ -7,6 +7,7 @@ import ( // Specificate the docs package _ "github.com/bancodobrasil/featws-resolver-adapter-go/docs" + "github.com/bancodobrasil/featws-resolver-adapter-go/middlewares" "github.com/bancodobrasil/featws-resolver-adapter-go/routes" "github.com/bancodobrasil/featws-resolver-adapter-go/services" ginMonitor "github.com/bancodobrasil/gin-monitor" @@ -34,6 +35,7 @@ func init() { viper.SetDefault("RESOLVER_LOG_JSON", false) viper.SetDefault("RESOLVER_LOG_LEVEL", "error") viper.SetDefault("RESOLVER_SERVICE_NAME", "resolver-adapter-go") + viper.SetDefault("RESOLVER_API_KEY", "") if err := viper.ReadInConfig(); err == nil { log.Infof("Using config file: %s", viper.ConfigFileUsed()) } @@ -84,6 +86,9 @@ func Run(resolverFunc services.ResolverFunc, config Config) error { services.SetupResolver(resolverFunc) router := gin.New() + + middlewares.InitializeMiddlewares() + // Register ginLogrus log format to gin router.Use(ginlogrus.Logger(log.StandardLogger()), gin.Recovery()) diff --git a/middlewares/middlewares.go b/middlewares/middlewares.go new file mode 100644 index 0000000..0f97138 --- /dev/null +++ b/middlewares/middlewares.go @@ -0,0 +1,18 @@ +package middlewares + +import "github.com/gin-gonic/gin" + +// Middleware ... +type Middleware interface { + Run() +} + +// InitializeMiddlewares ... +func InitializeMiddlewares() { + NewVerifyAPIKeyMiddleware() +} + +// Helper function to abort the request with an error status code and message +func respondWithError(c *gin.Context, code int, message interface{}) { + c.AbortWithStatusJSON(code, gin.H{"error": message}) +} diff --git a/middlewares/verify_api_key.go b/middlewares/verify_api_key.go new file mode 100644 index 0000000..f51ad14 --- /dev/null +++ b/middlewares/verify_api_key.go @@ -0,0 +1,51 @@ +package middlewares + +import ( + "github.com/gin-gonic/gin" + "github.com/spf13/viper" +) + +// VerifyAPIKeyMiddleware ... +type VerifyAPIKeyMiddleware struct { + key string +} + +var verifyAPIKeyMiddleware *VerifyAPIKeyMiddleware + +// VerifyAPIKey ... +func VerifyAPIKey() gin.HandlerFunc { + return verifyAPIKeyMiddleware.Run() +} + +// NewVerifyAPIKeyMiddleware ... +func NewVerifyAPIKeyMiddleware() { + verifyAPIKeyMiddleware = &VerifyAPIKeyMiddleware{ + key: viper.GetString("RESOLVER_API_KEY"), + } +} + +// Run ... +func (m *VerifyAPIKeyMiddleware) Run() gin.HandlerFunc { + return func(c *gin.Context) { + if m.key == "" { + c.Next() + return + } + + key := m.extractKeyFromHeader(c) + + if key != m.key { + respondWithError(c, 401, "Unauthorized") + } + + c.Next() + } +} + +func (m *VerifyAPIKeyMiddleware) extractKeyFromHeader(c *gin.Context) string { + authorizationHeader := c.Request.Header.Get("X-API-Key") + if authorizationHeader == "" { + respondWithError(c, 401, "Missing X-API-Key Header") + } + return authorizationHeader +} diff --git a/routes/api/v1/v1.go b/routes/api/v1/v1.go index b20e65c..3d4a261 100644 --- a/routes/api/v1/v1.go +++ b/routes/api/v1/v1.go @@ -1,10 +1,12 @@ package v1 import ( + "github.com/bancodobrasil/featws-resolver-adapter-go/middlewares" "github.com/gin-gonic/gin" ) // Router define routes the API V1 func Router(router *gin.RouterGroup) { + router.Use(middlewares.VerifyAPIKey()) resolveRouter(router.Group("/resolve")) }