diff --git a/README.md b/README.md
index 1a34db0bc0..6edfba384b 100644
--- a/README.md
+++ b/README.md
@@ -223,14 +223,21 @@
Graylog
+
+
+
+
+ Icinga2
+
+ |
+
+

Kibana
|
-
-

@@ -261,15 +268,15 @@
OpenSearch Serverless
|
+
+
+

Parseable
|
-
-
-

@@ -300,15 +307,15 @@
SignalFX
|
-
+
+ |
+
+

OpenObserve
|
-
-
-

@@ -339,15 +346,15 @@
ThousandEyes
|
-
+
+ |
+
+

UptimeKuma
|
-
-
-

diff --git a/docs/mint.json b/docs/mint.json
index 5028322a64..6fb6f16d9f 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -188,6 +188,7 @@
"providers/documentation/graylog-provider",
"providers/documentation/grok-provider",
"providers/documentation/http-provider",
+ "providers/documentation/icinga2-provider",
"providers/documentation/ilert-provider",
"providers/documentation/incidentio-provider",
"providers/documentation/incidentmanager-provider",
diff --git a/docs/providers/documentation/icinga2-provider.mdx b/docs/providers/documentation/icinga2-provider.mdx
new file mode 100644
index 0000000000..7031c2f0fb
--- /dev/null
+++ b/docs/providers/documentation/icinga2-provider.mdx
@@ -0,0 +1,122 @@
+---
+title: "Icinga2 Provider"
+sidebarTitle: "Icinga2"
+description: "Icinga2 Provider Allows Reception of Push Alerts from Icinga2 to Keep."
+---
+import AutoGeneratedSnippet from '/snippets/providers/icinga2-snippet-autogenerated.mdx';
+
+
+
+import ProviderLogo from '@components/ProviderLogo';
+
+
+
+# Icinga2 Provider
+
+The Icinga2 provider allows you to receive alerts from Icinga2 monitoring system within Keep.
+Icinga2 provider supports 2 methods for recieving alerts; Webhooks & API Polling.
+
+The recommended and primary method for receiving alerts is via Webhooks.
+
+## Setup
+
+### Prerequisites
+1. Access to an Icinga2 instance
+2. API user with relevant permissions
+3. Keep instance with webhook capability
+
+### Configuration
+
+The provider requires the following configuration:
+
+```yaml
+authentication:
+ host_url: "https://icinga2.example.com" # Your Icinga2 instance URL
+ api_user: "your-api-user" # Icinga2 API username
+ api_password: "your-api-password" # Icinga2 API password
+```
+
+### Webhook Configuration
+To configure Icinga2 to send alerts to Keep via webhooks:
+
+1. Navigate to your Icinga2 configuration directory
+2. Create or edit the ```eventcommands.conf``` file
+3. Add the following event command configuration:
+
+```plaintext
+object EventCommand "keep-notification" {
+ command = [ "curl" ]
+ arguments = {
+ "-X" = "POST"
+ "-H" = "Content-Type: application/json"
+ "-H" = "X-API-KEY: ${keep_api_key}"
+ "--data" = "{
+ \"host\": {
+ \"name\": \"$host.name$\",
+ \"display_name\": \"$host.display_name$\",
+ \"check_command\": \"$host.check_command$\",
+ \"acknowledgement\": \"$host.acknowledgement$\",
+ \"downtime_depth\": \"$host.downtime_depth$\",
+ \"flapping\": \"$host.flapping$\"
+ },
+ \"service\": {
+ \"name\": \"$service.name$\",
+ \"display_name\": \"$service.display_name$\",
+ \"check_command\": \"$service.check_command$\",
+ \"acknowledgement\": \"$service.acknowledgement$\",
+ \"downtime_depth\": \"$service.downtime_depth$\",
+ \"flapping\": \"$service.flapping$\"
+ },
+ \"check_result\": {
+ \"exit_status\": \"$service.state$\",
+ \"state\": \"$service.state_text$\",
+ \"output\": \"$service.output$\",
+ \"execution_start\": \"$service.last_check$\",
+ \"execution_end\": \"$service.last_check$\",
+ \"state_type\": \"$service.state_type$\",
+ \"attempt\": \"$service.check_attempt$\",
+ \"execution_time\": \"$service.execution_time$\",
+ \"latency\": \"$service.latency$\"
+ }
+ }"
+ "${keep_webhook_url}" = {
+ required = true
+ }
+ }
+}
+```
+4. Define variables in your Icinga2 Configuration:
+ - ```keep_api_key```: Your Keep API key with webhook role
+ - ```keep_webhook_url```: Your Keep Webhook URL
+5. Create a notification rule that uses this event command
+6. Restart Icinga2 to apply changes
+
+### State Mapping
+
+By Default, Icinga2 states are automatically mapped to Keep alert severities & statuses as follows:
+
+
+#### Status Mapping
+| Icinga2 State | Keep Status |
+|:--------------|:------------|
+| OK | RESOLVED |
+| WARNING | FIRING |
+| CRITICAL | FIRING |
+| UNKNOWN | FIRING |
+| UP | RESOLVED |
+| DOWN | FIRING |
+
+
+
+
+#### Severity Mapping
+| Icinga2 State | Keep Severity |
+|:--------------|:--------------|
+| OK | INFO |
+| WARNING | WARNING |
+| CRITICAL | CRITICAL |
+| UNKNOWN | INFO |
+| UP | INFO |
+| DOWN | CRITICAL |
+
+
\ No newline at end of file
diff --git a/docs/providers/overview.mdx b/docs/providers/overview.mdx
index 2222321108..39903e2e31 100644
--- a/docs/providers/overview.mdx
+++ b/docs/providers/overview.mdx
@@ -364,6 +364,14 @@ By leveraging Keep Providers, users are able to deeply integrate Keep with the t
}
>
+
+ }
+>
+
list[AlertDto]:
+ """
+ Get alerts from Icinga2 via API.
+
+ Returns:
+ list[AlertDto]: List of alerts in Keep format
+ """
+ self.logger.info("Getting alerts from Icinga2")
+
+ try:
+ response = requests.get(
+ url=f"{self.authentication_config.host_url}/v1/services?attrs=name,display_name,state,last_state_change",
+ auth=(
+ self.authentication_config.api_user,
+ self.authentication_config.api_password,
+ ),
+ verify=True,
+ )
+
+ if response.status_code != 200:
+ response.raise_for_status()
+
+ services = response.json()["results"]
+
+ return [
+ AlertDto(
+ id=service.get("name"),
+ name=service.get("display_name"),
+ status=self.STATUS_MAP.get(
+ service.get("state"), AlertStatus.FIRING
+ ),
+ severity=self.SEVERITY_MAP.get(
+ service.get("state"), AlertSeverity.INFO
+ ),
+ timestamp=service.get("last_state_change"),
+ source=["icinga2"],
+ )
+ for service in services
+ ]
+
+ except Exception as e:
+ self.logger.exception("Failed to get alerts from Icinga2")
+ raise Exception(f"Failed to get alerts from Icinga2: {str(e)}")
+
+ @staticmethod
+ def _format_alert(
+ event: dict, provider_instance: "BaseProvider" = None
+ ) -> AlertDto | list[AlertDto]:
+ """
+ Format Icinga2 webhook payload into Keep alert format.
+
+ Args:
+ event (dict): Raw alert data from Icinga2
+ provider_instance (BaseProvider, optional): Provider instance
+
+ Returns:
+ AlertDto: Formatted alert in Keep format
+ """
+ check_result = event.get("check_result", {})
+ service = event.get("service", {})
+ host = event.get("host", {})
+
+ status = check_result.get("exit_status", 0)
+ state = check_result.get("state", "UNKNOWN")
+ output = check_result.get("output", "No output provided")
+
+ alert = AlertDto(
+ id=service.get("name") or host.get("name"),
+ name=service.get("display_name") or host.get("display_name"),
+ status=Icinga2Provider.STATUS_MAP.get(state, AlertStatus.FIRING),
+ severity=Icinga2Provider.SEVERITY_MAP.get(state, AlertSeverity.INFO),
+ timestamp=check_result.get("execution_start"),
+ lastReceived=check_result.get("execution_end"),
+ description=output,
+ source=["icinga2"],
+ hostname=host.get("name"),
+ service_name=service.get("name"),
+ check_command=service.get("check_command") or host.get("check_command"),
+ state=state,
+ state_type=check_result.get("state_type"),
+ attempt=check_result.get("attempt"),
+ acknowledgement=service.get("acknowledgement")
+ or host.get("acknowledgement"),
+ downtime_depth=service.get("downtime_depth") or host.get("downtime_depth"),
+ flapping=service.get("flapping") or host.get("flapping"),
+ execution_time=check_result.get("execution_time"),
+ latency=check_result.get("latency"),
+ raw_output=output,
+ exit_status=status,
+ )
+
+ return alert
+
+
+if __name__ == "__main__":
+ import logging
+
+ logging.basicConfig(level=logging.DEBUG, handlers=[logging.StreamHandler()])
+
+ context_manager = ContextManager(
+ tenant_id="singletenant",
+ workflow_id="test",
+ )
+
+ import os
+
+ icinga2_api_user = os.getenv("ICINGA2_API_USER")
+ icinga2_api_password = os.getenv("ICINGA2_API_PASSWORD")
+
+ config = ProviderConfig(
+ description="Icinga2 Provider",
+ authentication={
+ "host_url": "https://icinga2.example.com",
+ "api_user": icinga2_api_user,
+ "api_password": icinga2_api_password,
+ },
+ )
+
+ provider = Icinga2Provider(context_manager, "icinga2", config)
|