-
Notifications
You must be signed in to change notification settings - Fork 702
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Jay Kumar <[email protected]> Co-authored-by: Shahar Glazner <[email protected]>
- Loading branch information
Showing
6 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
--- | ||
title: "Site24x7 Provider" | ||
description: "The Site24x7 Provider allows you to install webhooks and receive alerts in Site24x7. It manages authentication, setup of webhooks, and retrieval of alert logs from Site24x7." | ||
--- | ||
|
||
## Inputs | ||
|
||
The `Site24x7Provider` class handles authentication and interacts with the Site24x7 API to install webhooks and fetch alerts. Here are the primary methods and their parameters: | ||
|
||
### Main Class Methods | ||
|
||
- **`setup_webhook(tenant_id, keep_api_url, api_key, setup_alerts)`** | ||
- `tenant_id (str)`: Tenant identifier. | ||
- `keep_api_url (str)`: URL to send alert data. | ||
- `api_key (str)`: API key for authentication. | ||
- `setup_alerts (bool)`: Whether to setup alerting capabilities (default is True). | ||
|
||
- **`_get_alerts()`** | ||
- Returns a list of `AlertDto` objects representing the alerts. | ||
|
||
### Authentication Parameters | ||
|
||
The `Site24x7ProviderAuthConfig` class is used for API authentication and includes: | ||
|
||
- **`zohoRefreshToken (str)`**: Refresh token for Zoho authentication. *Required* | ||
- **`zohoClientId (str)`**: Client ID for Zoho authentication. *Required* | ||
- **`zohoClientSecret (str)`**: Client Secret for Zoho authentication. *Required* | ||
- **`zohoAccountTLD (str)`**: Top-Level Domain for the Zoho account. Options include `.com`, `.eu`, `.com.cn`, `.in`, `.com.au`, `.jp`. *Required* | ||
|
||
## Connecting with the Provider | ||
|
||
To use the Site24x7 Provider, initialize it with the necessary authentication credentials and provider configuration. Ensure that your Zoho account credentials (Client ID, Client Secret, and Refresh Token) are correctly set up in the `Site24x7ProviderAuthConfig`. | ||
|
||
## Steps to Obtain a Refresh Token | ||
|
||
1. **Registration and Client Credentials:** | ||
- Navigate to [Zoho API Console](https://api-console.zoho.com/). | ||
- Sign in or sign up using the email associated with your Site24x7 account. | ||
- Register your application using the "Self Client" option to get your Client ID and Client Secret. | ||
|
||
2. **Generating Grant Token:** | ||
- Go to the Zoho Developer Console and access your registered Self Client. | ||
- In the "Generate Code" tab, input the required scopes (`Site24x7.Admin.Read, Site24x7.Admin.Create, Site24x7.Operations.Read`), description, and time duration. | ||
- Click "Generate" and copy the provided code. | ||
|
||
3. **Generating Access and Refresh Tokens:** | ||
- Use the grant token to make a POST request to `https://accounts.zoho.com/oauth/v2/token` to obtain the access and refresh tokens. | ||
|
||
```bash | ||
curl -X POST 'https://accounts.zoho.com/oauth/v2/token' \ | ||
-d 'client_id=your_client_id' \ | ||
-d 'client_secret=your_client_secret' \ | ||
-d 'code=your_grant_token' \ | ||
-d 'grant_type=authorization_code' | ||
|
||
``` | ||
|
||
OR | ||
|
||
```python | ||
import requests | ||
response = requests.post( | ||
'https://accounts.zoho.com/oauth/v2/token', | ||
data={ | ||
'client_id': 'your_client_id', | ||
'client_secret': 'your_client_secret', | ||
'code': 'your_grant_token', | ||
'grant_type': 'authorization_code' | ||
} | ||
) | ||
refresh_token = response.json().get('refresh_token') | ||
``` | ||
|
||
--- | ||
## Notes | ||
|
||
- Ensure that the necessary scopes **Site24x7.Admin.Read, Site24x7.Admin.Create, Site24x7.Operations.Read** are included when generating the grant token, as they dictate the API functionalities accessible via the provider. | ||
- Zoho API Console [Link](https://api-console.zoho.com) | ||
|
||
--- | ||
|
||
## Useful Links | ||
|
||
- [Site24x7 API Documentation](https://www.site24x7.com/help/api/) | ||
- [Zoho OAuth Documentation](https://www.zoho.com/accounts/protocol/oauth/web-apps.html) | ||
- [Site 24x7 Authentication Guide](https://www.site24x7.com/help/api/#authentication) | ||
- [Third Party and Webhook Integrations](https://www.site24x7.com/help/api/#third-party-integrations) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
""" | ||
Site24x7Provider is a class that allows to install webhooks and get alerts in Site24x7. | ||
""" | ||
|
||
import dataclasses | ||
from typing import List, Optional | ||
from urllib.parse import urlencode, urljoin | ||
|
||
import pydantic | ||
import requests | ||
|
||
from keep.api.models.alert import AlertDto, AlertSeverity | ||
from keep.contextmanager.contextmanager import ContextManager | ||
from keep.providers.base.base_provider import BaseProvider | ||
from keep.providers.models.provider_config import ProviderConfig, ProviderScope | ||
|
||
|
||
class ResourceAlreadyExists(Exception): | ||
def __init__(self, *args): | ||
super().__init__(*args) | ||
|
||
|
||
@pydantic.dataclasses.dataclass | ||
class Site24X7ProviderAuthConfig: | ||
""" | ||
Site24x7 authentication configuration. | ||
""" | ||
zohoRefreshToken: str = dataclasses.field( | ||
metadata={ | ||
"required": True, | ||
"description": "ZohoRefreshToken", | ||
"hint": "Refresh token for Zoho authentication", | ||
"sensitive": True, | ||
}, | ||
) | ||
zohoClientId: str = dataclasses.field( | ||
metadata={ | ||
"required": True, | ||
"description": "ZohoClientId", | ||
"hint": "Client Secret for Zoho authentication.", | ||
"sensitive": True, | ||
}, | ||
) | ||
zohoClientSecret: str = dataclasses.field( | ||
metadata={ | ||
"required": True, | ||
"description": "ZohoClientSecret", | ||
"hint": "Password associated with yur account", | ||
"sensitive": True, | ||
}, | ||
) | ||
zohoAccountTLD: str = dataclasses.field( | ||
metadata={ | ||
"required": True, | ||
"description": "Zoho Account's TLD (.com | .eu | .com.cn | .in | .au | .jp)", | ||
"hint": "Possible: .com | .eu | .com.cn | .in | .com.au | .jp", | ||
}, | ||
) | ||
|
||
|
||
class Site24X7Provider(BaseProvider): | ||
"""Install Webhooks and receive alerts from Site24x7.""" | ||
|
||
PROVIDER_SCOPES = [ | ||
ProviderScope( | ||
name="authenticated", | ||
description="User is Authenticated", | ||
mandatory=True, | ||
mandatory_for_webhook=True, | ||
alias="Rules Reader", | ||
), | ||
ProviderScope( | ||
name="valid_tld", | ||
description="TLD is amongst the list [.com | .eu | .com.cn | .in | .com.au | .jp]", | ||
mandatory=True, | ||
mandatory_for_webhook=True, | ||
alias="Valid TLD", | ||
), | ||
] | ||
|
||
SEVERITIES_MAP = { | ||
"DOWN": AlertSeverity.WARNING, | ||
"TROUBLE": AlertSeverity.HIGH, | ||
"UP": AlertSeverity.INFO, | ||
"CRITICAL": AlertSeverity.CRITICAL | ||
} | ||
|
||
def __init__( | ||
self, context_manager: ContextManager, provider_id: str, config: ProviderConfig | ||
): | ||
super().__init__(context_manager, provider_id, config) | ||
|
||
def dispose(self): | ||
""" | ||
Dispose the provider. | ||
""" | ||
pass | ||
|
||
def validate_config(self): | ||
""" | ||
Validates required configuration for Site24x7 provider. | ||
""" | ||
self.authentication_config = Site24X7ProviderAuthConfig( | ||
**self.config.authentication | ||
) | ||
|
||
def __get_url(self, paths: List[str] = [], query_params: dict = None, **kwargs): | ||
""" | ||
Helper method to build the url for Site24x7 api requests. | ||
Example: | ||
paths = ["issue", "createmeta"] | ||
query_params = {"projectKeys": "key1"} | ||
url = __get_url("test", paths, query_params) | ||
# url = https://site24x7.com/api/2/issue/createmeta?projectKeys=key1 | ||
""" | ||
|
||
url = urljoin( | ||
f"https://www.site24x7{self.authentication_config.zohoAccountTLD}/api/", | ||
"/".join(str(path) for path in paths), | ||
) | ||
|
||
# add query params | ||
if query_params: | ||
url = f"{url}?{urlencode(query_params)}" | ||
|
||
return url | ||
|
||
def __get_headers(self): | ||
""" | ||
Getting the access token from Zoho API using the permanent refresh token. | ||
""" | ||
data = { | ||
'client_id': self.authentication_config.zohoClientId, | ||
'client_secret': self.authentication_config.zohoClientSecret, | ||
'refresh_token': self.authentication_config.zohoRefreshToken, | ||
'grant_type': 'refresh_token', | ||
} | ||
response = requests.post(f'https://accounts.zoho{self.authentication_config.zohoAccountTLD}/oauth/v2/token', | ||
data=data).json() | ||
return { | ||
'Authorization': f'Bearer {response["access_token"]}', | ||
} | ||
|
||
def validate_scopes(self) -> dict[str, bool | str]: | ||
valid_tlds = [".com", ".eu", ".com.cn", ".in", ".com.au", ".jp"] | ||
valid_tld_scope = "TLD not in [.com | .eu | .com.cn | .in | .com.au | .jp]" | ||
authentication_scope = "Validate TLD first" | ||
if self.authentication_config.zohoAccountTLD in valid_tlds: | ||
valid_tld_scope = True | ||
response = requests.get(f'{self.__get_url(paths=["monitors"])}', headers=self.__get_headers()) | ||
if response.status_code == 401: | ||
authentication_scope = response.json() | ||
self.logger.error("Failed to authenticate user", extra=authentication_scope) | ||
elif response.status_code == 200: | ||
authentication_scope = True | ||
self.logger.info("Authenticated user successfully") | ||
else: | ||
authentication_scope = f"Error while authenticating user, {response.status_code}" | ||
self.logger.error("Error while authenticating user", extra={"status_code": response.status_code}) | ||
return { | ||
'authenticated': authentication_scope, | ||
'valid_tld': valid_tld_scope, | ||
} | ||
|
||
def setup_webhook( | ||
self, tenant_id: str, keep_api_url: str, api_key: str, setup_alerts: bool = True | ||
): | ||
webhook_data = { | ||
"method": "P", | ||
"down_alert": True, | ||
"is_poller_webhook": False, | ||
"type": 8, | ||
"alert_tags_id": [], | ||
"custom_headers": [ | ||
{ | ||
"name": "X-API-KEY", | ||
"value": api_key | ||
} | ||
], | ||
"url": keep_api_url, | ||
"timeout": 30, | ||
"selection_type": 0, | ||
"send_in_json_format": True, | ||
"auth_method": "B", | ||
"trouble_alert": True, | ||
"critical_alert": True, | ||
"send_incident_parameters": True, | ||
"service_status": 0, | ||
"name": "KeepWebhook", | ||
"manage_tickets": False | ||
} | ||
response = requests.post(self.__get_url(paths=["integration/webhooks"]), json=webhook_data, | ||
headers=self.__get_headers()) | ||
if not response.ok: | ||
response_json = response.json() | ||
self.logger.error("Error while creating webhook", extra=response_json) | ||
raise Exception(response_json['message']) | ||
else: | ||
self.logger.info("Webhook created successfully") | ||
|
||
@staticmethod | ||
def _format_alert( | ||
event: dict, | ||
provider_instance: Optional["Site24X7Provider"] = None, | ||
) -> AlertDto: | ||
return AlertDto( | ||
url=event.get("MONITORURL", ""), | ||
lastReceived=event.get('INCIDENT_TIME', ""), | ||
description=event.get("INCIDENT_REASON", ""), | ||
name=event.get("MONITORNAME", ""), | ||
id=event.get("MONITOR_ID", ""), | ||
severity=Site24X7Provider.SEVERITIES_MAP.get(event.get("STATUS", "DOWN")), | ||
) | ||
|
||
def _get_alerts(self) -> list[AlertDto]: | ||
response = requests.get(self.__get_url(paths=['alert_logs']), headers=self.__get_headers()) | ||
if response.status_code == 200: | ||
alerts = [] | ||
response = response.json() | ||
for alert in response['data']: | ||
alerts.append( | ||
AlertDto( | ||
name=alert["display_name"], | ||
title=alert["msg"], | ||
startedAt=alert["sent_time"], | ||
) | ||
) | ||
return alerts | ||
else: | ||
self.logger.error("Failed to get alerts", extra=response.json()) | ||
raise Exception("Could not get alerts") |