Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
1 change: 1 addition & 0 deletions dev/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/validator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/validator/go.sum
Original file line number Diff line number Diff line change
@@ -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=
Expand Down
57 changes: 16 additions & 41 deletions src/validator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,21 @@ 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: "",
LogsApiUrl: "",
DebugErrs: true,
EnableRequestValidation: true,
EnableResponseValidation: false,
AllowUndefinedRoutes: allowUndefinedRoutesBool,
})
if err != nil {
log.Println("Failed to initialise Firetail middleware, err:", err.Error())
Expand Down Expand Up @@ -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
}

Expand All @@ -131,14 +118,21 @@ 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))),
LogsApiUrl: strings.TrimSpace(string(C.GoBytes(urlCharPtr, urlLength))),
DebugErrs: true,
EnableRequestValidation: false,
EnableResponseValidation: true,
AllowUndefinedRoutes: allowUndefinedRoutesBool,
})
if err != nil {
log.Println("Failed to initialise Firetail middleware, err:", err.Error())
Expand Down Expand Up @@ -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
}

Expand Down
Loading