diff --git a/README.md b/README.md index 8899d5f..b873c97 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,15 @@ To setup the Firetail NGINX Module, you will need to modify your `nginx.conf` to load_module modules/ngx_firetail_module.so; ``` -You can then use the `firetail_api_token` directive to provide your Firetail logging API token inside a http block like so: +You can then configure it using the following directives, which all belong in the `http` block of your NGINX configuration: -``` - firetail_api_token "YOUR-API-TOKEN"; -``` +| Directive | Description | Example | +| --------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| `firetail_api_token` | Your API token from the FireTail platform | `PS-02-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` | +| `firetail_url` | The URL of the API endpoint the FireTail NGINX module will send logs to. | `https://api.logging.eu-west-1.prod.firetail.app/logs/bulk` | +| `firetail_allow_undefined_routes` | If set to `1`, `t`, `T`, `TRUE`, `true`, or `True`, requests to routes not defined in your OpenAPI specification will not be blocked. | `1`, `t`, `T`, `TRUE`, `true`, `True`, `0`, `f`, `F`, `FALSE`, `false`, `False` | -See [dev/nginx.conf](./dev/nginx.conf) for an example of this in action. +See [dev/nginx.conf](./dev/nginx.conf) for an example of these in use. You should use a module such as the [ngx_http_lua_module](https://github.com/openresty/lua-nginx-module) to avoid placing plaintext credentials in your `nginx.conf`, and instead make use of [system environment variables](https://github.com/openresty/lua-nginx-module#system-environment-variable-support). diff --git a/dev/nginx.conf b/dev/nginx.conf index 9184880..3dd3c60 100644 --- a/dev/nginx.conf +++ b/dev/nginx.conf @@ -11,6 +11,7 @@ http { # You should use lua-nginx-module to pull the API token in from an environment variable here firetail_api_token "YOUR-API-TOKEN"; firetail_url "https://api.logging.eu-west-1.prod.firetail.app/logs/bulk"; + firetail_allow_undefined_routes "true"; server { listen 80; diff --git a/src/validator/go.mod b/src/validator/go.mod index 05d96bf..6b800bc 100644 --- a/src/validator/go.mod +++ b/src/validator/go.mod @@ -16,4 +16,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/FireTail-io/firetail-go-lib => github.com/FireTail-io/firetail-go-lib v0.2.1 +replace github.com/FireTail-io/firetail-go-lib => github.com/FireTail-io/firetail-go-lib v0.2.3 diff --git a/src/validator/go.sum b/src/validator/go.sum index 0fd7ba7..77fb7eb 100644 --- a/src/validator/go.sum +++ b/src/validator/go.sum @@ -1,5 +1,7 @@ github.com/FireTail-io/firetail-go-lib v0.2.1 h1:Jf3C1mAtCHAHHqSeuaMx6sSRmUS7OjgY4B2nY8XfibU= github.com/FireTail-io/firetail-go-lib v0.2.1/go.mod h1:PH4aGBwry6z/3vzXEdcMaxK22E3xqPq2+w2y3FzETj4= +github.com/FireTail-io/firetail-go-lib v0.2.3 h1:MDWnEpa/cyqc5sfhyHLjSXz8C+510nmHvpVxiOXnFAg= +github.com/FireTail-io/firetail-go-lib v0.2.3/go.mod h1:PH4aGBwry6z/3vzXEdcMaxK22E3xqPq2+w2y3FzETj4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/src/validator/main.go b/src/validator/main.go index 4ac87cb..a22393c 100644 --- a/src/validator/main.go +++ b/src/validator/main.go @@ -33,7 +33,13 @@ func ValidateRequestBody( log.Println("✅ Validating request body...") // Create the middleware if it hasn't already been done if firetailRequestMiddleware == nil { - var err error + allowUndefinedRoutesBool, err := strconv.ParseBool( + string(C.GoBytes(allowUndefinedRoutes, allowUndefinedRoutesLength)), + ) + if err != nil { + log.Println("Failed to initialise Firetail middleware, err:", err.Error()) + } + firetailRequestMiddleware, err = firetail.GetMiddleware(&firetail.Options{ OpenapiSpecPath: "/etc/nginx/appspec.yml", LogsApiToken: "", @@ -41,6 +47,7 @@ func ValidateRequestBody( DebugErrs: true, EnableRequestValidation: true, EnableResponseValidation: false, + AllowUndefinedRoutes: allowUndefinedRoutesBool, }) if err != nil { log.Println("Failed to initialise Firetail middleware, err:", err.Error()) @@ -90,26 +97,6 @@ func ValidateRequestBody( // If the body differs after being passed through the middleware then we'll just infer it doesn't match the spec if string(middlewareResponseBodyBytes) != string(placeholderResponse) { - // If allowing undefined routes, then we need to check if the response is a 404 from the middleware. If it is, - // we return success. - allowUndefinedRoutesBool, err := strconv.ParseBool(string(C.GoBytes(allowUndefinedRoutes, allowUndefinedRoutesLength))) - if err != nil { - return 1, responseCString // return 1 is error by convention - } - if allowUndefinedRoutesBool { - response_json := map[string]interface{}{} - if err := json.Unmarshal(middlewareResponseBodyBytes, &response_json); err != nil { - return 1, responseCString // return 1 is error by convention - } - if code, ok := response_json["code"]; ok { - if code_float, ok := code.(float64); ok { - if code_float == 404 { - return 0, responseCString // return 0 is success by convention - } - } - } - - } return 1, responseCString // return 1 is error by convention } @@ -131,7 +118,13 @@ func ValidateResponseBody( methodCharPtr unsafe.Pointer, methodLength C.int, ) (C.int, *C.char) { if firetailResponseMiddleware == nil { - var err error + allowUndefinedRoutesBool, err := strconv.ParseBool( + string(C.GoBytes(allowUndefinedRoutes, allowUndefinedRoutesLength)), + ) + if err != nil { + log.Println("Failed to initialise Firetail middleware, err:", err.Error()) + } + firetailResponseMiddleware, err = firetail.GetMiddleware(&firetail.Options{ OpenapiSpecPath: "/etc/nginx/appspec.yml", LogsApiToken: strings.TrimSpace(string(C.GoBytes(tokenCharPtr, tokenLength))), @@ -139,6 +132,7 @@ func ValidateResponseBody( DebugErrs: true, EnableRequestValidation: false, EnableResponseValidation: true, + AllowUndefinedRoutes: allowUndefinedRoutesBool, }) if err != nil { log.Println("Failed to initialise Firetail middleware, err:", err.Error()) @@ -204,25 +198,6 @@ func ValidateResponseBody( // If the body differs after being passed through the middleware then we'll just infer it doesn't match the spec if string(middlewareResponseBodyBytes) != string(resBodySlice) || localResponseWriter.Code != int(statusCode) { - // If allowing undefined routes, then we need to check if the response is a 404 from the middleware. If it is, - // we return success. - allowUndefinedRoutesBool, err := strconv.ParseBool(string(C.GoBytes(allowUndefinedRoutes, allowUndefinedRoutesLength))) - if err != nil { - return 1, responseCString // return 1 is error by convention - } - if allowUndefinedRoutesBool { - response_json := map[string]interface{}{} - if err := json.Unmarshal(middlewareResponseBodyBytes, &response_json); err != nil { - return 1, responseCString // return 1 is error by convention - } - if code, ok := response_json["code"]; ok { - if code_float, ok := code.(float64); ok { - if code_float == 404 { - return 0, C.CString(string(resBodySlice)) // return 0 is success by convention - } - } - } - } return 1, responseCString // return 1 is error by convention }