Skip to content

Commit

Permalink
feat: Add Nginx support (#22)
Browse files Browse the repository at this point in the history
* feat: Add Nginx njs script

Signed-off-by: Anurag Rajawat <[email protected]>

* feat: Add nginx-inc ingress controller support

Signed-off-by: Anurag Rajawat <[email protected]>

* docs: Add nginx docs

Signed-off-by: Anurag Rajawat <[email protected]>

---------

Signed-off-by: Anurag Rajawat <[email protected]>
  • Loading branch information
anurag-rajawat authored Nov 19, 2024
1 parent 840c0a4 commit b27c041
Show file tree
Hide file tree
Showing 20 changed files with 1,111 additions and 482 deletions.
12 changes: 12 additions & 0 deletions deployments/sentryflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ rules:
- delete
resources:
- wasmplugins
- apiGroups:
- ""
verbs:
- get
resources:
- configmaps
- apiGroups:
- apps
verbs:
- get
resources:
- deployments
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Expand Down
4 changes: 2 additions & 2 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions docs/receivers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
204 changes: 204 additions & 0 deletions docs/receivers/other/ingress-controller/nginx-inc/nginx_inc.md
Original file line number Diff line number Diff line change
@@ -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 <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: sentryflow-nginx-inc
namespace: <ingress-controller-namespace>
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: <nginx-ingress-controller-deploy-name>
configMapName: <nginx-ingress-configmap-name>
sentryFlowNjsConfigMapName: <sentryflow-nginx-inc-configmap-name>

receivers:
others:
- name: nginx-inc-ingress-controller # SentryFlow makes use of `name` to configure receivers. DON'T CHANGE IT.
namespace: <ingress-controller-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.
95 changes: 95 additions & 0 deletions docs/receivers/other/web-server/nginx/nginx.md
Original file line number Diff line number Diff line change
@@ -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://<sentryflow_url>/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.
Loading

0 comments on commit b27c041

Please sign in to comment.