From eb9ccb3aae0607e90421c2797e2d547963119b3b Mon Sep 17 00:00:00 2001 From: Anurag Rajawat Date: Mon, 18 Nov 2024 13:08:38 +0530 Subject: [PATCH] docs: Add nginx docs Signed-off-by: Anurag Rajawat --- docs/getting_started.md | 4 +- docs/receivers.md | 7 + .../ingress-controller/nginx-inc/nginx_inc.md | 204 ++++++++++++++++++ .../receivers/other/web-server/nginx/nginx.md | 95 ++++++++ 4 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 docs/receivers/other/ingress-controller/nginx-inc/nginx_inc.md create mode 100644 docs/receivers/other/web-server/nginx/nginx.md diff --git a/docs/getting_started.md b/docs/getting_started.md index 22d393f..a92706f 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -13,10 +13,10 @@ observability. It includes detailed commands for each step along with their expl ## 2. Deploying SentryFlow -Configure SentryFlow receiver by following [this](receivers.md). Then deploy SentryFlow by following `kubectl` command: +Configure SentryFlow receiver by following [this](receivers.md). Then deploy updated SentryFlow manifest by following `kubectl` command: ```shell -kubectl apply -f https://raw.githubusercontent.com/5GSEC/SentryFlow/refs/heads/main/deployments/sentryflow.yaml +kubectl apply -f sentryflow.yaml ``` This will create a namespace named `sentryflow` and will deploy the necessary Kubernetes resources. diff --git a/docs/receivers.md b/docs/receivers.md index 7b99638..73189b2 100644 --- a/docs/receivers.md +++ b/docs/receivers.md @@ -6,3 +6,10 @@ SentryFlow supports following receivers: - [Istio sidecar](https://istio.io/latest/docs/setup/) service mesh. To integrate SentryFlow with it, refer to [this](receivers/service-mesh/istio/istio.md). +- [Nginx Inc.](https://docs.nginx.com/nginx-ingress-controller/) ingress controller. To integrate SentryFlow with it, + refer to [this](receivers/other/ingress-controller/nginx-inc/nginx_inc.md). + +## Non-Kubernetes + +- [Nginx web server](https://nginx.org/) running on Virtual Machine or Bare-Metal. To integrate SentryFlow + with it, refer to [this](receivers/other/web-server/nginx/nginx.md). diff --git a/docs/receivers/other/ingress-controller/nginx-inc/nginx_inc.md b/docs/receivers/other/ingress-controller/nginx-inc/nginx_inc.md new file mode 100644 index 0000000..8179e4f --- /dev/null +++ b/docs/receivers/other/ingress-controller/nginx-inc/nginx_inc.md @@ -0,0 +1,204 @@ +# Nginx Incorporation Ingress Controller + +## Description + +This guide provides a step-by-step process to integrate SentryFlow +with [Nginx Inc.](https://docs.nginx.com/nginx-ingress-controller/) Ingress Controller, aimed at enhancing API +observability. It includes detailed commands for each step along with their explanations. + +SentryFlow make use of following to provide visibility into API calls: + +- [Nginx njs](https://nginx.org/en/docs/njs/) module. +- [Njs filter](../../../../../filter/nginx). + +## Prerequisites + +- Nginx Inc. Ingress Controller. + Follow [this](https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/) to deploy it. + +## How to + +To Observe API calls of your workloads served by Nginx inc. ingress controller in Kubernetes environment, follow +the below +steps: + +1. Create the following configmap in the same namespace as ingress controller. + +```shell +cat < +data: + sentryflow.js: | + const DEFAULT_KEY = "sentryFlow"; + const ResStatusKey = ":status" + const MAX_BODY_SIZE = 1_000_000; // 1 MB + + function requestHandler(r, data, flags) { + r.sendBuffer(data, flags); + r.done(); + + let responseBody = "" + try { + responseBody = new TextDecoder("utf-8") + .decode(new Uint8Array(data)); + } catch (error) { + r.error(`failed to decode data, error: ${error}`) + } + + if (responseBody.length > MAX_BODY_SIZE) { + responseBody = "" + } + + let apiEvent = { + "metadata": { + "timestamp": Date.parse(r.variables.time_iso8601.split("+")[0]) / 1000, + "receiver_name": "nginx", + "receiver_version": ngx.version, + }, + "source": { + "ip": r.remoteAddress, + "port": r.variables.remote_port, + }, + "destination": { + "ip": r.variables.server_addr, + "port": r.variables.server_port, + }, + "request": { + "headers": {}, + "body": r.requestText || "", + }, + "response": { + "headers": {}, + "body": responseBody, + }, + "protocol": r.variables.server_protocol, + }; + + for (const header in r.headersIn) { + apiEvent.request.headers[header] = r.headersIn[header]; + } + + apiEvent.request.headers[":scheme"] = r.variables.scheme + apiEvent.request.headers[":path"] = r.uri + apiEvent.request.headers[":method"] = r.variables.request_method + + apiEvent.request.headers["body_bytes_sent"] = r.variables.body_bytes_sent + + apiEvent.request.headers["request_length"] = r.variables.request_length + + apiEvent.request.headers["request_time"] = r.variables.request_time + + apiEvent.request.headers["query"] = r.variables.query_string + + for (const header in r.headersOut) { + apiEvent.response.headers[header] = r.headersOut[header]; + } + apiEvent.response.headers[ResStatusKey] = r.variables.status + + ngx.shared.apievents.set(DEFAULT_KEY, JSON.stringify(apiEvent)); + } + + async function dispatchHttpCall(r) { + try { + let apiEvent = ngx.shared.apievents.get(DEFAULT_KEY); + await r.subrequest("/sentryflow", { + method: "POST", body: apiEvent, detached: true + }) + } catch (error) { + r.error(`failed to dispatch HTTP call to SentryFlow, error: ${error}`) + return; + } finally { + ngx.shared.apievents.clear(); + } + + r.return(200, "OK"); + } + + export default {requestHandler, dispatchHttpCall}; +EOF +``` + +2. Add the following volume and volume-mount in ingress controller deployment: + +```yaml +... +volumes: + - name: sentryflow-nginx-inc + configMap: + name: sentryflow-nginx-inc +... +... +volumeMounts: + - mountPath: /etc/nginx/njs/sentryflow.js + name: sentryflow-nginx-inc + subPath: sentryflow.js +``` + +3. Update ingress controller configmap as follows: + +```yaml +... +data: + http-snippets: | + js_path "/etc/nginx/njs/"; + subrequest_output_buffer_size 8k; + js_shared_dict_zone zone=apievents:1M timeout=300s evict; + js_import main from sentryflow.js; + location-snippets: | + js_body_filter main.requestHandler buffer_type=buffer; + mirror /mirror_request; + mirror_request_body on; + server-snippets: | + location /mirror_request { + internal; + js_content main.dispatchHttpCall; + } + location /sentryflow { + internal; + # Update SentryFlow URL with path to ingest access logs if required. + proxy_pass http://sentryflow.sentryflow:8081/api/v1/events; + proxy_method POST; + proxy_set_header accept "application/json"; + proxy_set_header Content-Type "application/json"; + } +``` + +4. Download SentryFlow manifest file + + ```shell + curl -sO https://raw.githubusercontent.com/5GSEC/SentryFlow/refs/heads/main/deployments/sentryflow.yaml + ``` + +5. Update the `.receivers` configuration in `sentryflow` [configmap](../../../../../deployments/sentryflow.yaml) as + follows: + + ```yaml + filters: + server: + port: 8081 + # Following is required for `nginx-inc-ingress-controller` receiver. + nginxIngress: + deploymentName: + configMapName: + sentryFlowNjsConfigMapName: + + receivers: + others: + - name: nginx-inc-ingress-controller # SentryFlow makes use of `name` to configure receivers. DON'T CHANGE IT. + namespace: # Kubernetes namespace in which you've deployed the ingress controller. + ... + ``` + +6. Deploy SentryFlow + + ```shell + kubectl apply -f sentryflow.yaml + ``` + +7. Trigger API calls to generate traffic. + +8. Use SentryFlow [log client](../../../../client) to see the API Events. diff --git a/docs/receivers/other/web-server/nginx/nginx.md b/docs/receivers/other/web-server/nginx/nginx.md new file mode 100644 index 0000000..d426663 --- /dev/null +++ b/docs/receivers/other/web-server/nginx/nginx.md @@ -0,0 +1,95 @@ +# Nginx Web Server + +## Description + +This guide provides a step-by-step process to integrate SentryFlow +with [Nginx webserver](https://nginx.org/), aimed at enhancing API +observability. It includes detailed commands for each step along with their explanations. + +SentryFlow make use of following to provide visibility into API calls: + +- [Nginx njs](https://nginx.org/en/docs/njs/) module. +- [Njs filter](../../../../../filter/nginx). + +## Prerequisites + +- Nginx web server. +- [Nginx-njs-module](https://github.com/nginx/njs?tab=readme-ov-file#downloading-and-installing). + +## How to + +To Observe API calls of your application running on a virtual machine (VM) behind a Nginx web server, follow the below +steps: + +1. Copy [sentryflow.js](../../../../../filter/nginx/sentryflow.js) file to `/etc/nginx/njs/` directory as + `sentryflow.js`. +2. Edit `nginx.conf` file located in `/etc/nginx/` directory as follows: + +```nginx configuration +load_module /etc/nginx/modules/ngx_http_js_module.so; +... +http { + ... + subrequest_output_buffer_size 8k; + js_path "/etc/nginx/njs/"; + js_shared_dict_zone zone=apievents:1M timeout=60s evict; + js_import main from sentryflow.js; + ... + server { + location / { + js_body_filter main.requestHandler buffer_type=buffer; + mirror /mirror_request; + mirror_request_body on; + } + + location /mirror_request { + internal; + js_content main.dispatchHttpCall; + } + + location /sentryflow { + internal; + + # SentryFlow URL with path to ingest access logs. + proxy_pass http:///api/v1/events; + + proxy_method POST; + proxy_set_header accept "application/json"; + proxy_set_header Content-Type "application/json"; + } + ... + } +} +``` + +Here is the sample [nginx.conf](../../../../../filter/nginx/nginx.conf) file for reference. + +3. Reload `nginx`: + +```shell +$ sudo nginx -s reload +``` + +4. Update the `.receivers` configuration in `sentryflow` [configmap](../../../../deployments/sentryflow.yaml) as + follows: + + ```yaml + filters: + server: + port: 8081 + + receivers: + others: + - name: nginx-webserver # SentryFlow makes use of `name` to configure receivers. DON'T CHANGE IT. + ... + ``` + +5. Deploy SentryFlow + + ```shell + kubectl apply -f sentryflow.yaml + ``` + +6. Trigger API calls to generate traffic. + +7. Use SentryFlow [log client](../../../../client) to see the API Events. \ No newline at end of file