diff --git a/docs/features/github/tutorials/automated-pull-requests.mdx b/docs/features/github/tutorials/automated-pull-requests.mdx
index 5eef4f9a4..2ae2a5cd6 100644
--- a/docs/features/github/tutorials/automated-pull-requests.mdx
+++ b/docs/features/github/tutorials/automated-pull-requests.mdx
@@ -45,7 +45,7 @@ kubectl apply -n otterize-tutorial-github -f ${ABSOLUTE_URL}/code-examples/githu
```
-Once the deployment is complete , you can view the application's network map on Otterize Cloud. Turn on `Assume default deny` under network policies, as shown in the picture below.
+Once the deployment is complete, you can view the application's network map on Otterize Cloud. Turn on `Assume default deny` under network policies, as shown in the picture below.
Finally, merge the pull request and deploy the updated ClientIntents manifest.
diff --git a/docs/features/gitlab/_category_.json b/docs/features/gitlab/_category_.json
new file mode 100644
index 000000000..c4065447e
--- /dev/null
+++ b/docs/features/gitlab/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "GitLab",
+ "position": 6,
+ "collapsed": true,
+ "customProps": {
+ "image": "/img/icons/gitlab-logo.svg"
+ }
+}
diff --git a/docs/features/gitlab/index.mdx b/docs/features/gitlab/index.mdx
new file mode 100644
index 000000000..7d69209e6
--- /dev/null
+++ b/docs/features/gitlab/index.mdx
@@ -0,0 +1,33 @@
+---
+sidebar_position: 1
+title: GitLab | Overview
+hide_table_of_contents: true
+hide_title: true
+---
+
+import DocsLinkCard from "@site/src/components/LinkCard";
+
+export const tutorials = [
+ {
+ title: 'Automated authorization merge requests',
+ description: 'Automatically create merge requests to resolve any drifts detected in your cluster',
+ url: '/features/gitlab/tutorials/automated-merge-requests'
+ },
+];
+
+
+# GitLab
+With the GitLab integration, Otterize automatically opens merge requests when it detects differences between policies defined in ClientIntents and actual application traffic.
+
+### Tutorials
+
+To learn how to leverage Otterize's continuous monitoring of your cluster's access to detect and resolve any drifts.
+
+
+### How does Otterize work with GitLab?
+
+After you deploy ClientIntents and enable enforcement, any traffic that doesn't match the configured intents is blocked. With the GitLab integration, Otterize continuously compares the ClientIntents stored in your remote repository with the traffic the Network Mapper detects in your cluster.
+
+If changes in your application's traffic patterns are detected, Otterize automatically submits a merge request to your chosen branch, updating the ClientIntents in your remote repository to reflect the actual traffic. This approach significantly reduces frictions for developers, allowing discrepancies to be resolved easily through familiar GitOps workflows.
+
+Alternatively, you can use the GitLab integration in shadow mode. In this mode, Otterize does not enforce any intents but continues updating the ClientIntents in your remote repository. This setup lets you gradually build the necessary ClientIntents for intended access without risking blocked connections. Once you stop receiving new merge requests for new connections, you can be confident that all required ClientIntents are declared and proceed to activate enforcement.
diff --git a/docs/features/gitlab/reference.mdx b/docs/features/gitlab/reference.mdx
new file mode 100644
index 000000000..bca3187f4
--- /dev/null
+++ b/docs/features/gitlab/reference.mdx
@@ -0,0 +1,30 @@
+---
+sidebar_position: 3
+title: Reference
+---
+
+## Triggers
+
+#### About
+
+Teams adopt various strategies for organizing their repositories, including creating separate repositories for individual clusters, namespaces, and services or using branches to represent different states of deployment. Triggers enhance this organizational flexibility, enabling you to tailor the mapping of your environment to your GitLab repositories according to your specific requirements. You can fine-tune the GitLab integration by configuring multiple triggers to align precisely with your needs.
+
+#### On Trigger
+
+The *On Trigger* configurations define the trigger’s scope, limiting it to only the specific contexts required to be monitored for changes. This allows targeted workflows, such as tracking changes in the *Staging* environment to prepare intents for an upcoming production release.
+
+| Item | Description |
+|--------------|--------------------------------------------------------------|
+| Clusters | Relates to a Kubernetes cluster integrated into Otterize. The names associated with the cluster are those provided during the integration. |
+| Environments | One or more environments (testing, staging, production, etc.) are to be monitored for changes. Default is *All* |
+| Namespaces | One or more Kubernetes namespaces to be monitored for changes. Default is *All* |
+| Services | One or more Kubernetes Services to be monitored for changes. Default is *All* |
+#### Open merge request On
+
+The *Open merge request on* definition associates the *On Trigger* scope to a specific GitLab project, branch, and directory path in your .
+
+| Item | Description |
+|--------------------|--------------------------------------------------------------|
+| Project | Refers to the owner or group and project name combination that uniquely identifies a project in GitLab. For example, Otterizes network mapper would be supplied by `otterize/network-mapper` |
+| Base branch | Base branch for most repositories is `main` or `master`. |
+| ClientIntents path | The path from the repository root folder that contains the intent definition files. For instance: `/helm/intents/` |
diff --git a/docs/features/gitlab/tutorials/_category_.json b/docs/features/gitlab/tutorials/_category_.json
new file mode 100644
index 000000000..e04728744
--- /dev/null
+++ b/docs/features/gitlab/tutorials/_category_.json
@@ -0,0 +1,5 @@
+{
+ "label": "Tutorials",
+ "position": 1,
+ "collapsed": false
+}
diff --git a/docs/features/gitlab/tutorials/automated-merge-requests.mdx b/docs/features/gitlab/tutorials/automated-merge-requests.mdx
new file mode 100644
index 000000000..09b94278a
--- /dev/null
+++ b/docs/features/gitlab/tutorials/automated-merge-requests.mdx
@@ -0,0 +1,230 @@
+---
+sidebar_position: 1
+title: Automated authorization merge requests
+image: /img/quick-tutorials/gitlab/social.png
+---
+
+Otterize integrates with GitLab projects to automatically generate merge requests as application access requirements change in the cluster. This enables platform administrators to continuously align security requirements with code updates.
+
+In this tutorial, you will:
+
+- Deploy a sample application.
+- Create a Git repository to store ClientIntents manifests.
+- Integrate a new Git repository into Otterize Cloud and install Otterize’s GitLab app.
+- Modify application communication patterns, thereby triggering Otterize to create a merge request with the updated ClientIntents.
+
+## Prerequisites
+
+### CLI tools
+You will need the following CLI tools to set up the repository and export ClientIntents:
+
+1. [Otterize CLI](https://docs.otterize.com/overview/installation#install-the-otterize-cli)
+2. [GitLab CLI](https://gitlab.com/gitlab-org/cli)
+
+After installation, log in with `glab auth login` and select your preferred method for authentication. Ensure your account has the necessary permissions to create new repositories.
+
+### Deploy Otterize
+
+
+With a Kubernetes cluster ready, head over to [Otterize Cloud](https://app.otterize.com/) and navigate to the [integrations page](https://app.otterize.com/integrations) to deploy Otterize. Follow the provided instructions to integrate your cluster.
+
+## Tutorial
+
+### Deploy the application
+
+Use the following command to set up the tutorial namespace and deploy a sample application simulating a fantasy tabletop game. The application comprises several services responsible for different aspects of the game.
+
+```yaml
+kubectl apply -n otterize-tutorial-gitlab -f ${ABSOLUTE_URL}/code-examples/gitlab/all.yaml
+```
+
+ View Deployment
+
+```yaml
+{@include: ../../../../static/code-examples/gitlab/all.yaml}
+```
+
+
+Once the deployment is complete, you can view the application's network map on Otterize Cloud. Turn on `Assume default deny` under network policies, as shown in the picture below.
+
+
+
+The connections will turn red.
+
+
+
+
+### Export and apply ClientIntents
+
+Otterize can automatically generate application access rules based on the actual network traffic detected by the network-mapper.
+
+Use the Otterize CLI tool to export the recommended intent definitions. You can also access these definitions directly from the Access Graph on Otterize Cloud.
+
+```bash
+mkdir otterize-tutorial-gitlab
+cd otterize-tutorial-gitlab
+mkdir intents
+otterize network-mapper export -n otterize-tutorial-gitlab > ./intents/intents.yaml
+```
+
+ View intents.yaml
+
+```yaml
+apiVersion: k8s.otterize.com/v1alpha3
+kind: ClientIntents
+metadata:
+ name: adventure
+ namespace: otterize-tutorial-gitlab
+spec:
+ service:
+ name: adventure
+ calls:
+ - name: character-generator
+ - name: monster-generator
+ - name: quest-generator
+ - name: treasure-generator
+```
+
+
+Next, secure the application's pods by applying these intents to the cluster.
+
+```bash
+kubectl apply -n otterize-tutorial-gitlab -f ./intents/intents.yaml
+```
+In the Access Graph, the *adventure* client is now allowed to access the protected services.
+
+
+### Create the GitLab repository
+
+To ensure versioned records, create a GitLab repository, stage and commit the applied intents. Then push the changes to the main branch.
+
+Make sure you are in the `otterize-tutorial-gitlab` directory before executing the following commands.
+
+```bash
+export GLAB_USER=$(glab api user | jq -r '.username')
+glab repo create otterize-tutorial-gitlab --private
+git init
+git add .
+git commit -m "Initial Intents"
+git branch -M main
+
+# for HTTPS access, use git remote add origin https://gitlab.com/$GLAB_USER/otterize-tutorial-gitlab.git
+git remote add origin git@gitlab.com:$GLAB_USER/otterize-tutorial-gitlab.git
+git push -u origin main
+```
+
+The repository can now be integrated to Otterize cloud to detect drifts in case of changes in traffic patterns.
+
+### Add the GitLab repository to Otterize Cloud
+
+:::tip
+In this section, you will use the *main* branch to track ClientIntents changes. For production environments, we recommend monitoring traffic changes in other long-held branches, such as *development*, *test*, or *staging*. You can then deploy the new compiled ClientIntents in production with your preferred tool.
+:::
+
+To add the repository to Otterize Cloud, navigate to the [Integrations page](https://app.otterize.com/integrations).
+
+1. Click `Add Integration`.
+2. Select integration type: `GitLab`.
+3. Provide the name *otterize-tutorial-gitlab* as the integration.
+4. In the `On Trigger` section, select your Kubernetes cluster, and leave the other options set to the predefined defaults.
+5. In the `Open merge request on` section, select the `Project` field, and provide the owner and organization names in the form: */otterize-tutorial-gitlab*.
+6. Select the `Base Branch` field, and enter *main*.
+7. Select the `ClientIntents path` field, and enter `intents`. It represents the relative path hosting the ClientIntents manifests.
+8. Next, click the `Add` button. This will redirect you to GitLab. If needed, click `Authorize` to authorize the Otterize Cloud GitLab app to use your account.
+
+
+
+The Otterize GitLab app is now installed in your account. Otterize will continuously monitor for differences between the ClientIntents definitions in your repository and the actual usage detected in your cluster. If drifts are detected, merge requests will be automatically opened to update the intent definitions and reflect the new usage behaviors.
+
+You can learn more about GitLab configuration and how to use the Triggers on the [Reference page](/features/gitlab/reference)
+
+### Update the application
+
+In the original deployment, the game simulation's *adventure* pod utilized the *monster-generator* pod to fetch a random monster. An improved version, *monster-generator-v2*, has just been released and is ready for deployment.
+
+```bash
+kubectl apply -n otterize-tutorial-gitlab -f ${ABSOLUTE_URL}/code-examples/gitlab/all-v2.yaml
+```
+
+Once the pod is deployed, check the logs of the *adventure* pod using the command below. It should reflect the new application version.
+
+```bash
+kubectl logs -f -n otterize-tutorial-gitlab deploy/adventure
+```
+
+Here is an example of the expected output.
+
+```
+****************************************************
+Let another great adventure begin!
+****************************************************
+Using MonsterV2 generated monster
+Welcome to your adventure, Elf Wizard!
+Your quest: Escort the Caravan
+Beware, a wild Elephant appears!
+The Elephant has 90 hit points, Our Elf has 244 points.
+---------------------------------------------
+Elf lands a 19 point strike against the smelly Beast!
+Elephant hits our strong Elf doing 20 point of damage.
+The Elephant has 71 hit points, Our Elf has 224 points.
+```
+
+*monster-generator-v2* is now displayed in Otterize Cloud Access Graph.
+
+
+
+### Check for a new merge request
+
+Following the introduction of a new application component, the network-mapper has detected a new connection and updated Otterize cloud. This update has triggered the GitLab integration, resulting in the submission of a new merge request.
+
+
+
+Finally, merge the merge request and deploy the updated ClientIntents manifest.
+
+```text
+glab mr merge 1 -y
+kubectl apply -n otterize-tutorial-gitlab -f ./intents/intents.yaml
+```
+
+## Teardown
+
+Delete the application.
+
+```*bash*
+kubectl delete namespace otterize-tutorial-gitlab
+```
+
+Delete the Git repository with the following command:
+
+```bash
+glab repo delete $GLAB_USER/otterize-tutorial-gitlab
+```
+:::note
+If your API doesn't grant *delete* privileges, navigate to the repository's *Settings* section to delete it manually.
+:::
+
+Finally, you can delete your local copy of the repository.
+
+```bash
+cd ..
+rm -rf otterize-tutorial-gitlab
+```
diff --git a/docs/getting-started/README.mdx b/docs/getting-started/README.mdx
index a9e5d1e5c..1c71ad0eb 100644
--- a/docs/getting-started/README.mdx
+++ b/docs/getting-started/README.mdx
@@ -63,6 +63,11 @@ export const features = [
title: 'GitHub',
icon: '/img/icons/github-logo.svg',
url: '/features/github/'
+ },
+ {
+ title: 'GitLab',
+ icon: '/img/icons/gitlab-logo.svg',
+ url: '/features/gitlab/'
}
];
diff --git a/static/code-examples/gitlab/all-v2.yaml b/static/code-examples/gitlab/all-v2.yaml
new file mode 100644
index 000000000..639e0df7a
--- /dev/null
+++ b/static/code-examples/gitlab/all-v2.yaml
@@ -0,0 +1,190 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: otterize-tutorial-gitlab
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: adventure
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: adventure
+ template:
+ metadata:
+ labels:
+ app: adventure
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./adventure"]
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: character-generator
+spec:
+ selector:
+ matchLabels:
+ app: character-generator
+ template:
+ metadata:
+ labels:
+ app: character-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./character-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: quest-generator
+spec:
+ selector:
+ matchLabels:
+ app: quest-generator
+ template:
+ metadata:
+ labels:
+ app: quest-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./quest-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: monster-generator
+spec:
+ selector:
+ matchLabels:
+ app: monster-generator
+ template:
+ metadata:
+ labels:
+ app: monster-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./monster-generator"]
+ ports:
+ - containerPort: 8080
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: treasure-generator
+spec:
+ selector:
+ matchLabels:
+ app: treasure-generator
+ template:
+ metadata:
+ labels:
+ app: treasure-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./treasure-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: monster-generator-v2
+spec:
+ selector:
+ matchLabels:
+ app: monster-generator-v2
+ template:
+ metadata:
+ labels:
+ app: monster-generator-v2
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./monster-generator-v2"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: treasure-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: treasure-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: character-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: character-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: monster-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: monster-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: quest-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: quest-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: monster-generator-v2
+spec:
+ type: ClusterIP
+ selector:
+ app: monster-generator-v2
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
\ No newline at end of file
diff --git a/static/code-examples/gitlab/all.yaml b/static/code-examples/gitlab/all.yaml
new file mode 100644
index 000000000..8c974fef6
--- /dev/null
+++ b/static/code-examples/gitlab/all.yaml
@@ -0,0 +1,157 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: otterize-tutorial-gitlab
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: adventure
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: adventure
+ template:
+ metadata:
+ labels:
+ app: adventure
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./adventure"]
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: character-generator
+spec:
+ selector:
+ matchLabels:
+ app: character-generator
+ template:
+ metadata:
+ labels:
+ app: character-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./character-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: quest-generator
+spec:
+ selector:
+ matchLabels:
+ app: quest-generator
+ template:
+ metadata:
+ labels:
+ app: quest-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./quest-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: monster-generator
+spec:
+ selector:
+ matchLabels:
+ app: monster-generator
+ template:
+ metadata:
+ labels:
+ app: monster-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./monster-generator"]
+ ports:
+ - containerPort: 8080
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: treasure-generator
+spec:
+ selector:
+ matchLabels:
+ app: treasure-generator
+ template:
+ metadata:
+ labels:
+ app: treasure-generator
+ spec:
+ containers:
+ - name: github-tutorial
+ image: otterize/github-tutorial:latest
+ args: ["./treasure-generator"]
+ ports:
+ - containerPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: treasure-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: treasure-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: character-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: character-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: monster-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: monster-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: quest-generator
+spec:
+ type: ClusterIP
+ selector:
+ app: quest-generator
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+---
\ No newline at end of file
diff --git a/static/img/icons/gitlab-logo.svg b/static/img/icons/gitlab-logo.svg
new file mode 100644
index 000000000..44f5ed717
--- /dev/null
+++ b/static/img/icons/gitlab-logo.svg
@@ -0,0 +1,9 @@
+
diff --git a/static/img/quick-tutorials/gitlab/authorize-gitlab-app.png b/static/img/quick-tutorials/gitlab/authorize-gitlab-app.png
new file mode 100644
index 000000000..2d60ec563
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/authorize-gitlab-app.png differ
diff --git a/static/img/quick-tutorials/gitlab/merge-request.png b/static/img/quick-tutorials/gitlab/merge-request.png
new file mode 100644
index 000000000..4df76c81a
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/merge-request.png differ
diff --git a/static/img/quick-tutorials/gitlab/protected-services.gif b/static/img/quick-tutorials/gitlab/protected-services.gif
new file mode 100644
index 000000000..545e4a410
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/protected-services.gif differ
diff --git a/static/img/quick-tutorials/gitlab/social.png b/static/img/quick-tutorials/gitlab/social.png
new file mode 100644
index 000000000..d3efdf871
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/social.png differ
diff --git a/static/img/quick-tutorials/gitlab/visual-graph-assume-default-deny.png b/static/img/quick-tutorials/gitlab/visual-graph-assume-default-deny.png
new file mode 100644
index 000000000..953dea645
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/visual-graph-assume-default-deny.png differ
diff --git a/static/img/quick-tutorials/gitlab/visual-graph-intents-applied.png b/static/img/quick-tutorials/gitlab/visual-graph-intents-applied.png
new file mode 100644
index 000000000..c23baf9bf
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/visual-graph-intents-applied.png differ
diff --git a/static/img/quick-tutorials/gitlab/visual-graph-unsecure-deploy.png b/static/img/quick-tutorials/gitlab/visual-graph-unsecure-deploy.png
new file mode 100644
index 000000000..3b502014e
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/visual-graph-unsecure-deploy.png differ
diff --git a/static/img/quick-tutorials/gitlab/visual-graph-updated-services.png b/static/img/quick-tutorials/gitlab/visual-graph-updated-services.png
new file mode 100644
index 000000000..8ac89b015
Binary files /dev/null and b/static/img/quick-tutorials/gitlab/visual-graph-updated-services.png differ