Details
| ID | Grafana |
|---|---|
| Provider | Grafana Labs |
| Category | Analytics & SIEM |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Grafana alerting service.
This integration was integrated and tested with version 8.0.0 of Grafana
Configure Grafana in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | True | |
| Username | True | |
| Password | True | |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Maximum number of incidents to fetch | Maximum is limited to 200. | False |
| Fetch incidents | False | |
| First fetch time interval | False | |
| Dashboard IDs to fetch | A comma-separated list of dashboard IDs. Can be found by running the “grafana-dashboards-search” command. | False |
| Panel ID to fetch | See “help”. | False |
| Alert name to fetch | False | |
| States to fetch | False | |
| Incident type | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
grafana-alerts-list
Gets alerts.
Base Command
grafana-alerts-list
Input
| Argument Name | Description | Required |
|---|---|---|
| dashboard_id | A comma-separated list of dashboard IDs by which to filter the results. | Optional |
| panel_id | The ID of the panel by which to filter the results. | Optional |
| name | Value that is contained in the alert’s name by which to filter the results. | Optional |
| state | A comma-separated list of states by which to filter the results. The options are: all, no_data, paused, alerting, ok, pending, unknown. | Optional |
| limit | The maximum number of alerts to return. | Optional |
| folder_id | A comma-separated list of folder IDs by which to filter the results. | Optional |
| dashboard_name | Value that is contained in the dashboard’s name by which to filter the results. | Optional |
| dashboard_tag | A comma-separated list of dashboard tags by which to filter the results. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Alert.id | Number | Alert ID. |
| Grafana.Alert.dashboardId | Number | Alert dashboard ID. |
| Grafana.Alert.dashboardUid | String | Alert dashboard UID. |
| Grafana.Alert.dashboardName | String | Alert dashboard name. |
| Grafana.Alert.panelId | Number | Alert panel ID. |
| Grafana.Alert.name | String | Alert name. |
| Grafana.Alert.state | String | Alert state. |
| Grafana.Alert.newStateDate | Date | The date on which the new alert state appeared. |
| Grafana.Alert.evalDate | Date | The date the alert was evaluated. |
| Grafana.Alert.evalData | Unknown | The metric that triggered the alert and made it change to the alerting state. |
| Grafana.Alert.executionError | String | Alert execution error. |
| Grafana.Alert.url | String | Alert URL. |
Command Example
#### Context Example
```json
{
"Grafana": {
"Alert": [
{
"dashboardId": 2,
"dashboardName": "streaming2",
"dashboardUid": "yzDQUOR7z",
"evalData": {
"noData": true
},
"evalDate": "0001-01-01T00:00:00Z",
"executionError": "",
"id": 2,
"name": "Adi's Alert",
"newStateDate": "2021-09-30T15:43:20Z",
"panelId": 5,
"state": "unknown",
"url": "https://base_url/d/yzDQUOR7z/streaming2"
},
{
"dashboardId": 1,
"dashboardName": "streaming",
"dashboardUid": "TXSTREZ",
"evalData": {
"noData": true
},
"evalDate": "0001-01-01T00:00:00Z",
"executionError": "",
"id": 1,
"name": "Arseny's Alert",
"newStateDate": "2021-06-09T15:20:01Z",
"panelId": 4,
"state": "no_data",
"url": "https://base_url/d/TXSTREZ/streaming"
},
{
"dashboardId": 2,
"dashboardName": "streaming2",
"dashboardUid": "yzDQUOR7z",
"evalData": {
"noData": true
},
"evalDate": "0001-01-01T00:00:00Z",
"executionError": "",
"id": 3,
"name": "TryAlert",
"newStateDate": "2021-08-11T13:30:40Z",
"panelId": 6,
"state": "alerting",
"url": "https://base_url/d/yzDQUOR7z/streaming2"
}
]
}
}
Human Readable Output
Existing Alerts
Id Name State New State Date Panel Id Dashboard Id Dashboard Uid Dashboard Name Url 2 Adi’s Alert no_data 2021-09-30T15:43:20Z 5 2 yzDQUOR7z streaming2 https://base_url/d/yzDQUOR7z/streaming2 1 Arseny’s Alert no_data 2021-06-09T15:20:01Z 4 1 TXSTREZ streaming https://base_url/d/TXSTREZ/streaming 3 TryAlert alerting 2021-08-11T13:30:40Z 6 2 yzDQUOR7z streaming2 https://base_url/d/yzDQUOR7z/streaming2
grafana-alert-pause
Pauses an alert by ID.
Base Command
grafana-alert-pause
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | ID of the alert to pause. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Alert.id | Number | The ID of the alert that was paused. |
| Grafana.Alert.state | String | The new state of the alert. |
Command Example
!grafana-alert-pause alert_id=2
Context Example
{
"Grafana": {
"Alert": {
"id": 2,
"message": "Alert paused",
"state": "paused"
}
}
}
Human Readable Output
Paused Alert 2
Id Message State 2 Alert paused paused
grafana-alert-unpause
Unpauses an alert by ID.
Base Command
grafana-alert-unpause
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | ID of the alert to unpause. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Alert.id | Number | The ID of the alert that was unpaused. |
| Grafana.Alert.state | String | The new state of the alert. |
Command Example
!grafana-alert-unpause alert_id=2
Context Example
{
"Grafana": {
"Alert": {
"id": 2,
"message": "Alert un-paused",
"state": "unknown"
}
}
}
Human Readable Output
Un-paused Alert 2
Id Message State 2 Alert un-paused unknown
grafana-users-search
Gets users.
Base Command
grafana-users-search
Input
| Argument Name | Description | Required |
|---|---|---|
| perpage | Number of results to return per page. | Optional |
| page | Index of the page of results to retrieve. | Optional |
| query | The value contained in either the name, login, or email fields by which to filter the results. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.User.id | Number | User ID. |
| Grafana.User.name | String | User name. |
| Grafana.User.login | String | User login. |
| Grafana.User.email | String | User email. |
| Grafana.User.avatarUrl | String | User avatar URL. |
| Grafana.User.isAdmin | Boolean | Is user an admin? |
| Grafana.User.isDisabled | Boolean | Is user disabled? |
| Grafana.User.lastSeenAt | Date | The date the user was last seen. |
| Grafana.User.lastSeenAtAge | String | When the user was last seen in minutes (m), years (Y), month (M), days (d), etc. |
| Grafana.User.authLabels | Unknown | User authentication labels |
Command Example
#### Context Example
```json
{
"Grafana": {
"User": [
{
"authLabels": [],
"avatarUrl": "https://base_url/avatar/5d9c68c6c50ed3d02a2fcf54f63993b",
"email": "User@mail",
"id": 1,
"isAdmin": true,
"isDisabled": false,
"lastSeenAt": "2021-10-04T15:25:40Z",
"lastSeenAtAge": "4m",
"login": "admin",
"name": "admin"
},
{
"authLabels": [],
"avatarUrl": "https://base_url/avatar/04501192ea3453723d1336c6520ce2c",
"email": "xadmin",
"id": 2,
"isAdmin": false,
"isDisabled": false,
"lastSeenAt": "2021-09-29T12:47:23Z",
"lastSeenAtAge": "5d",
"login": "xadmin",
"name": "xadmin"
}
]
}
}
Human Readable Output
Existing Users
Id Name Login Is Admin Is Disabled Avatar Url Last Seen At Last Seen At Age 1 User@mail admin admin true false https://base_url/avatar/5d9c68c6c50ed3d02a2fcf54f63993b 2021-10-04T15:25:40Z 4m 2 xadmin xadmin xadmin false false https://base_url/avatar/04501192ea3453723d1336c6520ce2c 2021-09-29T12:47:23Z 5d 3 test@test User3 User false false https://base_url/avatar/46d229b033af06a191ff2267bca9ae5 2011-07-27T15:10:37Z 10y
grafana-user-teams-get
Gets the user’s teams by user ID.
Base Command
grafana-user-teams-get
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | ID of user for whom to get teams. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.User.id | Number | User ID. |
| Grafana.User.teams.id | Number | Team ID. |
| Grafana.User.teams.orgId | Number | Team organization ID. |
| Grafana.User.teams.name | String | Team name. |
| Grafana.User.teams.email | String | Team email. |
| Grafana.User.teams.avatarUrl | String | Team avatar URL. |
| Grafana.User.teams.memberCount | Number | Team member count. |
| Grafana.User.teams.permission | Number | Number of team permissions. |
Command Example
!grafana-user-teams-get user_id=1
Context Example
{
"Grafana": {
"User": {
"id": "1",
"teams": [
{
"avatarUrl": "https://base_url/avatar/f1f97cfa3c828a7352da671a",
"email": "team@test.com",
"id": 15,
"memberCount": 1,
"name": "Test Team",
"orgId": 1,
"permission": 0
},
{
"avatarUrl": "https://base_url/avatar/1d3226029e424011bffde2f",
"email": "test2@test.com",
"id": 16,
"memberCount": 2,
"name": "TestTeam2",
"orgId": 1,
"permission": 0
}
]
}
}
}
Human Readable Output
Teams For User 1
Id Org Id Name Avatar Url Member Count Permission 15 1 Test Team team@test.com https://base_url/avatar/f1f97cfa3c828a7352da671a 1 0 16 1 TestTeam2 test2@test.com https://base_url/avatar/1d3226029e424011bffde2f 2 0
grafana-user-orgs-get
Gets user’s organizations by user ID.
Base Command
grafana-user-orgs-get
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | ID of user for whom to get the organizations. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.User.id | Number | User ID. |
| Grafana.User.orgs.orgId | Number | Organization ID. |
| Grafana.User.orgs.name | String | Organization name. |
| Grafana.User.orgs.role | String | Organization role. |
Command Example
!grafana-user-orgs-get user_id=1
Context Example
{
"Grafana": {
"User": {
"id": "1",
"orgs": [
{
"name": "Main Org.",
"orgId": 1,
"role": "Admin"
},
{
"name": "New Org.",
"orgId": 2,
"role": "Admin"
}
]
}
}
}
Human Readable Output
Organizations For User 1
Name Org Id Role Main Org. 1 Admin New Org. 2 Admin
grafana-user-update
Updates a user by user ID. Login or email is mandatory. If you change your own login information, you won’t be able to continue querying as your username (login) will change. Login and email should be unique.
Base Command
grafana-user-update
Input
| Argument Name | Description | Required |
|---|---|---|
| User email. If email is not specified, login must be specified. | Optional | |
| name | User’s name. | Optional |
| login | User login (username). If login is not specified, email must be specified. | Optional |
| theme | User theme when using Grafana’s interface. Possilble values: “light” or “dark”. Possible values are: light, dark. | Optional |
| user_id | User ID. | Required |
Context Output
There is no context output for this command.
Command Example
!grafana-user-update user_id=3 email=TestUser login=TestUser name=TestUser
Human Readable Output
Successfully Updated User 3
Message User updated
grafana-annotation-create
Creates an annotation in the Grafana database. The dashboard_id and panel_id fields are optional. If they are not specified, a global annotation is created and can be queried in any dashboard that adds the Grafana annotations data source. When creating a region annotation include the time_end property.
Base Command
grafana-annotation-create
Input
| Argument Name | Description | Required |
|---|---|---|
| dashboard_id | Dashboard ID. | Optional |
| panel_id | Panel ID. | Optional |
| time | Start time. | Optional |
| time_end | End time. | Optional |
| tags | A comma-separated list of tags by which to filter the dashboards to add the annotation to. | Optional |
| text | Text of the annotation. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Annotation.id | Number | Annotation ID. |
Command Example
!grafana-annotation-create text="annotate"
Context Example
{
"Grafana": {
"Annotation": {
"id": 266,
"message": "Annotation added"
}
}
}
Human Readable Output
Successfully Created Annotation 266
Id Message 266 Annotation added
grafana-teams-search
Gets teams.
Base Command
grafana-teams-search
Input
| Argument Name | Description | Required |
|---|---|---|
| perpage | Number of results to return on a page. | Optional |
| page | Index of the page of results to retrieve. | Optional |
| query | The value contained in the name of a team. | Optional |
| name | The exact name of the team. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Team.id | Number | Team ID. |
| Grafana.Team.orgId | Number | Team organization ID. |
| Grafana.Team.name | String | Team name. |
| Grafana.Team.email | String | Team email. |
| Grafana.Team.avatarUrl | String | Team avatar URL. |
| Grafana.Team.memberCount | Number | The number of team members. |
| Grafana.Team.permission | Number | Number of team permissions. |
Command Example
#### Context Example
```json
{
"Grafana": {
"Team": [
{
"avatarUrl": "https://base_url/avatar/f1f97cfa3c828a7352da671a",
"email": "team@test.com",
"id": 15,
"memberCount": 1,
"name": "Test Team",
"orgId": 1,
"permission": 0
},
{
"avatarUrl": "https://base_url/avatar/1d3226029e424011bffde2f",
"email": "test2@test.com",
"id": 16,
"memberCount": 2,
"name": "TestTeam2",
"orgId": 1,
"permission": 0
},
{
"avatarUrl": "https://base_url/avatar/71cc610bc4841e3444235f09d9c",
"email": "email@test.com",
"id": 144,
"memberCount": 0,
"name": "Elia",
"orgId": 1,
"permission": 0
}
]
}
}
Human Readable Output
Teams Search Results
Id Org Id Name Avatar Url Member Count Permission 15 1 Test Team team@test.com https://base_url/avatar/f1f97cfa3c828a7352da671a 1 0 16 1 TestTeam2 test2@test.com https://base_url/avatar/1d3226029e424011bffde2f 2 0 144 1 Elia email@test.com https://base_url/avatar/71cc610bc4841e3444235f09d9c 0 0
grafana-team-members-list
Gets a list of all team members by team ID.
Base Command
grafana-team-members-list
Input
| Argument Name | Description | Required |
|---|---|---|
| team_id | Team ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Team.id | Number | Team ID. |
| Grafana.Team.members.orgId | Number | Member organization ID. |
| Grafana.Team.members.teamId | Number | Member team ID. |
| Grafana.Team.members.userId | Number | Member user ID. |
| Grafana.Team.members.auth_module | String | Member authentication module. |
| Grafana.Team.members.email | String | Member email. |
| Grafana.Team.members.name | String | Member name. |
| Grafana.Team.members.login | String | Member login. |
| Grafana.Team.members.avatarUrl | String | Member avatar URL. |
| Grafana.Team.members.labels | Unknown | Member labels. |
| Grafana.Team.members.permission | Number | Member permission. |
Command Example
!grafana-team-members-list team_id=15
Context Example
{
"Grafana": {
"Team": {
"id": "15",
"members": [
{
"auth_module": "",
"avatarUrl": "https://base_url/avatar/5d9c68c6c50ed3d02a2fcf54f63993b",
"email": "User@mail",
"labels": [],
"login": "admin",
"name": "admin",
"orgId": 1,
"permission": 0,
"teamId": 15,
"userId": 1
}
]
}
}
}
Human Readable Output
Team 15 Members
Org Id Team Id User Id Name Login Avatar Url Permission 1 15 1 User@mail admin admin https://base_url/avatar/5d9c68c6c50ed3d02a2fcf54f63993b 0
grafana-user-add-to-team
Adds a user to a team.
Base Command
grafana-user-add-to-team
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | User ID. | Required |
| team_id | Team ID. | Required |
Context Output
There is no context output for this command.
Command Example
!grafana-user-add-to-team team_id=15 user_id=3
Human Readable Output
Successfully Added User 3 to Team 15
Message Member added to Team
grafana-user-remove-from-team
Removes a user from a team.
Base Command
grafana-user-remove-from-team
Input
| Argument Name | Description | Required |
|---|---|---|
| team_id | Team ID. | Required |
| user_id | User ID. | Required |
Context Output
There is no context output for this command.
Command Example
!grafana-user-remove-from-team team_id=15 user_id=3
Human Readable Output
Successfully Removed User 3 from Team 15
Message Team Member removed
grafana-team-add
Creates a new team.
Base Command
grafana-team-add
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The team name. Must be unique. | Required |
| Email address of the team. | Optional | |
| org_id | Organization ID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Team.id | Number | Team ID. |
Command Example
!grafana-team-add name="TestTeam4"
Context Example
{
"Grafana": {
"Team": {
"id": 153,
"message": "Team created"
}
}
}
Human Readable Output
Successfully Created Team 153
Message Team Id Team created 153
grafana-team-delete
Deletes a team.
Base Command
grafana-team-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| team_id | Team ID. | Required |
Context Output
There is no context output for this command.
Command Example
!grafana-team-delete team_id=152
Human Readable Output
Successfully Deleted Team 152
Message Team deleted
grafana-org-create
Creates an organization.
Base Command
grafana-org-create
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name of the organization. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Organization.id | Number | Organization ID. |
Command Example
!grafana-org-create name="Organization"
Context Example
{
"Grafana": {
"Organization": {
"id": 12,
"message": "Organization created"
}
}
}
Human Readable Output
Successfully Created Organization 12
Message Org Id Organization created 12
grafana-dashboards-search
Searches dashboards.
Base Command
grafana-dashboards-search
Input
| Argument Name | Description | Required |
|---|---|---|
| query | Value is contained in the name of the dashboard. | Optional |
| tag | A comma-separated list of tags by which to filter the results. | Optional |
| type | Type of the dashboard. Possible values: “dash-folder” and “dash-db”. Possible values are: dash-folder, dash-db. | Optional |
| dashboard_ids | A comma-separated list of dashboard IDs by which to filter the results. | Optional |
| folder_ids | A comma-separated list of folder IDs by which to filter the results. | Optional |
| starred | Whether to only return starred dashboards. Possible values: “true” and “false”. Possible values are: true, false. | Optional |
| limit | The maximum number of dashboards to return. | Optional |
| page | Page. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Dashboard.id | Number | Dashboard ID. |
| Grafana.Dashboard.uid | String | Dashboard UID. |
| Grafana.Dashboard.title | String | Dashboard title. |
| Grafana.Dashboard.uri | String | Dashboard URI. |
| Grafana.Dashboard.url | String | Dashboard URL |
| Grafana.Dashboard.slug | String | Dashboard slug. |
| Grafana.Dashboard.type | String | Dashboard type. |
| Grafana.Dashboard.tags | Unknown | Dashboard tags. |
| Grafana.Dashboard.isStarred | Boolean | Is dashboard starred? |
Command Example
#### Context Example
```json
{
"Grafana": {
"Dashboard": [
{
"id": 1,
"isStarred": true,
"slug": "",
"tags": [],
"title": "Streaming",
"type": "dash-db",
"uid": "TXSTREZ",
"uri": "db/streaming",
"url": "https://base_url/d/TXSTREZ/streaming"
},
{
"id": 2,
"isStarred": false,
"slug": "",
"tags": [
"tag1"
],
"title": "Streaming Simple",
"type": "dash-db",
"uid": "yzDQUOR7z",
"uri": "db/streaming2",
"url": "https://base_url/d/yzDQUOR7z/streaming2"
}
]
}
}
Human Readable Output
Existing Dashboards
Id Uid Title Is Starred Tags Uri Url Type Sort Meta 1 TXSTREZ Streaming true db/streaming https://base_url/d/TXSTREZ/streaming dash-db 0 2 yzDQUOR7z Streaming Simple false tag1 db/streaming2 https://base_url/d/yzDQUOR7z/streaming2 dash-db 0
grafana-user-get-by-id
Gets a user by ID.
Base Command
grafana-user-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | User ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.User.id | Number | User ID. |
| Grafana.User.email | String | User email. |
| Grafana.User.name | String | User name. |
| Grafana.User.login | String | User login. |
| Grafana.User.theme | String | User theme. |
| Grafana.User.orgId | Number | Organization ID. |
| Grafana.User.isGrafanaAdmin | Boolean | Is user a Grafana admin? |
| Grafana.User.isDisabled | Boolean | Is user disabled? |
| Grafana.User.isExternal | Boolean | Is user external? |
| Grafana.User.updatedAt | Date | Date when user was updated. |
| Grafana.User.createdAt | Date | Date when user was created. |
| Grafana.User.avatarUrl | String | User avatar URL. |
| Grafana.User.authLabels | Unknown | User authentication labels. |
Command Example
!grafana-user-get-by-id user_id=1
Context Example
{
"Grafana": {
"User": {
"authLabels": [],
"avatarUrl": "/avatar/46d229b033af06a191ff2267bca9ae5",
"createdAt": "2021-06-08T10:57:39Z",
"email": "User@mail",
"id": 1,
"isDisabled": false,
"isExternal": false,
"isGrafanaAdmin": true,
"login": "admin",
"name": "admin",
"orgId": 1,
"theme": "light",
"updatedAt": "2021-09-30T14:46:22Z"
}
}
}
Human Readable Output
User 1 Results
Id Name Login Theme Org Id Is Grafana Admin Is D Is abled Is External Updated At Created At Avatar Url 1 User@mail admin admin light 1 true false false 2021-09-30T14:46:22Z 2021-06-08T10:57:39Z https://base_url/avatar/46d229b033af06a191ff2267bca9ae5
grafana-team-get-by-id
Gets a team by ID.
Base Command
grafana-team-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| team_id | Team ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Team.id | Number | Team ID. |
| Grafana.Team.orgId | Number | Team organization ID. |
| Grafana.Team.name | String | Team name. |
| Grafana.Team.email | String | Team email. |
| Grafana.Team.avatarUrl | String | Team avatar URL. |
| Grafana.Team.memberCount | Number | The number of team members. |
| Grafana.Team.permission | Number | Number of team permissions. |
Command Example
!grafana-team-get-by-id team_id=15
Context Example
{
"Grafana": {
"Team": {
"avatarUrl": "https://base_url/avatar/f1f97cfa3c828a7352da671a",
"email": "team@test.com",
"id": 15,
"memberCount": 1,
"name": "Test Team",
"orgId": 1,
"permission": 0
}
}
}
Human Readable Output
Team 15 Results
Id Org Id Name Avatar Url Member Count Permission 15 1 Test Team team@test.com https://base_url/avatar/f1f97cfa3c828a7352da671a 1 0
grafana-alert-get-by-id
Gets an alert by id.
Base Command
grafana-alert-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | Alert ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Alert.id | Number | Alert ID. |
| Grafana.Alert.version | Number | Alert version. |
| Grafana.Alert.orgId | Number | Alert organization ID. |
| Grafana.Alert.dashboardId | Number | Alert dashboard ID. |
| Grafana.Alert.panelId | Number | Alert panel ID. |
| Grafana.Alert.name | String | Alert name. |
| Grafana.Alert.message | String | Alert message. |
| Grafana.Alert.severity | String | Alert severity. |
| Grafana.Alert.state | String | Alert state. |
| Grafana.Alert.handler | Number | Alert handler. |
| Grafana.Alert.silenced | Boolean | Whether the alert was silenced. |
| Grafana.Alert.executionError | String | Alert execution error. |
| Grafana.Alert.frequency | Number | Alert frequency in seconds. |
| Grafana.Alert.for | Number | Once the alert rule has been firing for more than this duration in nanoseconds, then the alert changes to “Alerting”. Otherwise it goes from “OK” to “Pending”. |
| Grafana.Alert.evalData | Unknown | The metric that triggered the alert and made it change to the “Alerting” state. |
| Grafana.Alert.newStateDate | Date | The date of the alert’s new state. |
| Grafana.Alert.stateChanges | Number | The number of time the alert state changes. |
| Grafana.Alert.created | Date | Date the alert was created. |
| Grafana.Alert.updated | Date | Date the alert was updated. |
| Grafana.Alert.settings | Unknown | Alert settings. |
Command Example
!grafana-alert-get-by-id alert_id=1
Context Example
{
"Grafana": {
"Alert": {
"created": "2021-06-09T15:13:45Z",
"dashboardId": 1,
"evalData": {
"noData": true
},
"executionError": " ",
"for": 60000000000,
"frequency": 600,
"handler": 1,
"id": 1,
"message": "man down!",
"name": "Arseny's Alert",
"newStateDate": "2021-06-09T15:20:01Z",
"orgId": 1,
"panelId": 4,
"settings": {
"alertRuleTags": {
"moshe": "2"
},
"conditions": [
{
"evaluator": {
"params": [
10
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"datasourceId": 1,
"model": {
"refId": "A",
"scenarioId": "streaming_client",
"stream": {
"noise": 2.2,
"speed": 100,
"spread": 3.5,
"type": "signal"
},
"stringInput": ""
},
"params": [
"A",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "avg"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "1m",
"frequency": "10m",
"handler": 1,
"message": "man down!",
"name": "Arseny's Alert",
"noDataState": "no_data",
"notifications": []
},
"severity": "",
"silenced": false,
"state": "no_data",
"stateChanges": 1,
"updated": "2021-06-09T15:14:51Z",
"version": 0
}
}
}
Human Readable Output
Alert 1 Results
Id Version Org Id Dashboard Id Panel Id Name Message State New State Date State Changes Handler Silenced Frequency For Created Updated 1 0 1 1 4 Arseny’s Alert man down! no_data 2021-06-09T15:20:01Z 1 1 false 600 60000000000 2021-06-09T15:13:45Z 2021-06-09T15:14:51Z
grafana-org-list
Gets organizations.
Base Command
grafana-org-list
Input
| Argument Name | Description | Required |
|---|---|---|
| perpage | Number of results to return on a page. | Optional |
| page | Index of the page of results to retrieve. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Organization.id | Number | Organization ID. |
| Grafana.Organization.name | String | Organization name. |
Command Example
#### Context Example
```json
{
"Grafana": {
"Organization": [
{
"id": 1,
"name": "Main Org."
},
{
"id": 2,
"name": "New Org."
},
{
"id": 12,
"name": "Organization"
}
]
}
}
Human Readable Output
Existing Organizations
Id Name 1 Main Org. 2 New Org. 12 Organization
grafana-org-get-by-name
Gets an organization by name.
Base Command
grafana-org-get-by-name
Input
| Argument Name | Description | Required |
|---|---|---|
| name | The exact name of the organization to get. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Organization.id | Number | Organization ID. |
| Grafana.Organization.name | String | Organization name. |
| Grafana.Organization.address | Unknown | Organization address. |
Command Example
!grafana-org-get-by-name name="Main Org."
Context Example
{
"Grafana": {
"Organization": {
"address": {
"address1": "",
"address2": "",
"city": "",
"country": "",
"state": "",
"zipCode": ""
},
"id": 1,
"name": "Main Org."
}
}
}
Human Readable Output
Organization “Main Org.” Results
Name Id Address Main Org. 1 address1:
address2:
city:
zipCode:
state:
country:
grafana-org-get-by-id
Gets an organization by ID.
Base Command
grafana-org-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| org_id | Organization ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Grafana.Organization.id | Number | Organization ID. |
| Grafana.Organization.name | String | Organization name. |
| Grafana.Organization.address | Unknown | Organization address. |
Command Example
!grafana-org-get-by-id org_id=1
Context Example
{
"Grafana": {
"Organization": {
"address": {
"address1": "",
"address2": "",
"city": "",
"country": "",
"state": "",
"zipCode": ""
},
"id": 1,
"name": "Main Org."
}
}
}
Human Readable Output
Organization 1 Results
Id Name Address 1 Main Org. address1:
address2:
city:
zipCode:
state:
country:
Configuration parameters
url— Server URL (required)credentials— Username (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)max_fetch— Maximum number of incidents to fetchisFetch— Fetch incidentsfirst_fetch— First fetch time intervaldashboard_id— Dashboard IDs to fetchpanel_id— Panel ID to fetchalert_name— Alert name to fetchstate— States to fetchincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (22)
-
grafana-alert-get-by-idGets an alert by id.
-
grafana-alert-pausePauses an alert by ID.
-
grafana-alert-unpauseUnpauses an alert by ID.
-
grafana-alerts-listGets alerts.
-
grafana-annotation-createCreates an annotation in the Grafana database. The dashboard_id and panel_id fields are optional. If they are not specified, a global annotation is created and can be queried in any dashboard that adds the Grafana annotations data source. When creating a region annotation include the time_end property.
-
grafana-dashboards-searchSearches dashboards.
-
grafana-org-createCreates an organization.
-
grafana-org-get-by-idGets an organization by ID.
-
grafana-org-get-by-nameGets an organization by name.
-
grafana-org-listGets organizations.
-
grafana-team-addCreates a new team.
-
grafana-team-deleteDeletes a team.
-
grafana-team-get-by-idGets a team by ID.
-
grafana-team-members-listGets a list of all team members by team ID.
-
grafana-teams-searchGets teams.
-
grafana-user-add-to-teamAdds a user to a team.
-
grafana-user-get-by-idGets a user by ID.
-
grafana-user-orgs-getGets user's organizations by user ID.
-
grafana-user-remove-from-teamRemoves a user from a team.
-
grafana-user-teams-getGets the user's teams by user ID.
-
grafana-user-updateUpdates a user by user ID. Login or email is mandatory. If you change your own login information, you won't be able to continue querying as your username (login) will change. Login and email should be unique.
-
grafana-users-searchGets users.
import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from pytz import utc from CommonServerUserPython import * # noqa """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR HEADERS = {"Accept": "application/json", "Content-Type": "application/json"} # In the documentation, the state 'all' is written as 'ALL'. As the latter doesn't work, we use 'all''. ALERT_STATES = {"all", "no_data", "paused", "alerting", "ok", "pending", "unknown"} MAX_INCIDENTS_TO_FETCH = 200 FETCH_DEFAULT_TIME = "3 days" """ CLIENT CLASS """ class Client(BaseClient): def __init__(self, server_url, verify=True, proxy=False, headers=None, auth=None): super().__init__(base_url=server_url, verify=verify, proxy=proxy, headers=headers, auth=auth) def alerts_list_request( self, dashboard_id: Optional[List[str]] = None, panel_id: str = None, query: str = None, state: List[str] = None, limit: str = None, folder_id: List[str] = None, dashboard_query: str = None, dashboard_tag: List[str] = None, ): # query works this way- we can get it with parenthesis or without, it adds to it params = assign_params( dashboardId=dashboard_id, panelId=panel_id, query=query, state=state, limit=limit, folderId=folder_id, dashboardQuery=dashboard_query, dashboardTag=dashboard_tag, ) response = self._http_request("GET", "api/alerts", params=params, headers=self._headers) response = self._concatenate_urls(response) return response def alert_pause_request(self, alert_id: str, paused: bool): data = {"paused": paused} response = self._http_request("POST", f"api/alerts/{alert_id}/pause", json_data=data, headers=self._headers) return response def alert_get_by_id_request(self, alert_id: str): response = self._http_request("GET", f"api/alerts/{alert_id}", headers=self._headers) return response def users_search_request(self, page_size: str = None, page_number: str = None, query: str = None): params = assign_params(perpage=page_size, page=page_number, query=query) response = self._http_request("GET", "api/users", params=params, headers=self._headers) response = self._concatenate_urls(response, "avatarUrl") return response def user_get_by_id_request(self, user_id: str): response = self._http_request("GET", f"api/users/{user_id}", headers=self._headers) response = self._concatenate_url(response, "avatarUrl") return response def users_teams_request(self, user_id: str): response = self._http_request("GET", f"api/users/{user_id}/teams", headers=self._headers) response = self._concatenate_urls(response, "avatarUrl") return response def users_organization_request(self, user_id: str): response = self._http_request("GET", f"api/users/{user_id}/orgs", headers=self._headers) return response def user_update_request(self, user_id: str, email: str = None, name: str = None, login: str = None, theme: str = None): data = {"email": email, "login": login, "name": name, "theme": theme} response = self._http_request("PUT", f"api/users/{user_id}", json_data=data, headers=self._headers) return response def annotation_create_request( self, text: str, dashboard_id: int = None, panel_id: int = None, time_start: int = None, time_end: int = None, tags: List[str] = None, ): data = { "dashboardId": dashboard_id, "panelId": panel_id, "tags": tags, "text": text, "time": time_start, "timeEnd": time_end, } response = self._http_request("POST", "api/annotations", json_data=data, headers=self._headers) return response def teams_search_request(self, page_size: str = None, page_number: str = None, query: str = None, name: str = None): params = assign_params(perpage=page_size, page=page_number, query=query, name=name) response = self._http_request("GET", "api/teams/search", params=params, headers=self._headers) response = self._concatenate_urls(response["teams"], "avatarUrl") return response def team_get_by_id_request(self, team_id: str): response = self._http_request("GET", f"api/teams/{team_id}", headers=self._headers) response = self._concatenate_url(response, "avatarUrl") return response def team_members_request(self, team_id: str): response = self._http_request("GET", f"api/teams/{team_id}/members", headers=self._headers) response = self._concatenate_urls(response, "avatarUrl") return response def user_add_to_team_request(self, team_id: str, user_id: str): data = {"userId": int(user_id)} # 400 - 'User is already added to this team' might be raised - which isn't a real error response = self._http_request( "POST", f"api/teams/{team_id}/members", json_data=data, headers=self._headers, ok_codes=(200, 400) ) return response def user_remove_from_team_request(self, team_id: str, user_id: str): response = self._http_request("DELETE", f"api/teams/{team_id}/members/{user_id}", headers=self._headers) return response def team_add_request(self, name: str, email: str = None, org_id: str = None): data = {"email": email, "name": name, "orgId": org_id} response = self._http_request("POST", "api/teams", json_data=data, headers=self._headers) return response def team_delete_request(self, team_id: str): response = self._http_request("DELETE", f"api/teams/{team_id}", headers=self._headers) return response def org_create_request(self, name: str): data = {"name": name} response = self._http_request("POST", "api/orgs", json_data=data, headers=self._headers) return response def org_list_request(self, page_size: str = None, page_number: str = None): params = assign_params(perpage=page_size, page=page_number) response = self._http_request("GET", "api/orgs", params=params, headers=self._headers) return response def org_get_by_name_request(self, name: str): response = self._http_request("GET", f"api/orgs/name/{name}", headers=self._headers) return response def org_get_by_id_request(self, org_id: str = None): response = self._http_request("GET", f"api/orgs/{org_id}", headers=self._headers) return response def dashboards_search_request( self, query: str = None, tag: List[str] = None, type_: str = None, dashboard_ids: List[str] = None, folder_ids: List[str] = None, starred: str = None, limit: str = None, page_number: str = None, ): params = assign_params( query=query, tag=tag, type=type_, dashboardIds=dashboard_ids, folderIds=folder_ids, starred=starred, limit=limit, page=page_number, ) response = self._http_request("GET", "api/search", params=params, headers=self._headers) response = self._concatenate_urls(response) return response def _concatenate_urls(self, responses: List[Dict[str, Any]], url_field: str = "url"): """ Concatenates a url suffix with the base url for the places where only a suffix is returned. Updates the list of dicts given, and returns it. """ for response in responses: self._concatenate_url(response, url_field) return responses def _concatenate_url(self, response: Dict[str, Any], url_field: str = "url"): """ Concatenates a url suffix with the base url for the places where only a suffix is returned, so urls we display will be clickable and lead to a real place. Updates the dict given, and returns it. """ if url_field in response: url = urljoin(self._base_url, response[url_field]) response[url_field] = url return response """ HELPER FUNCTIONS """ def set_time_to_epoch_millisecond(time_to_set: Optional[str] = None): """ For annotation creation, sets the time to epoch numbers in millisecond resolution - if it was filled. """ if time_to_set: # noqa: RET503 time_to_set_date = dateparser.parse(time_to_set) assert time_to_set_date is not None return int(time_to_set_date.timestamp()) * 1000 def change_key(response: dict, prev_key: str, new_key: str): """ This function changes a key in response, so the values could be aggregated with other functions. """ if prev_key in response: response[new_key] = response.pop(prev_key) demisto.debug(f'changing key "{prev_key}" in response to "{new_key}", edited response is: {response}') return response def keys_to_lowercase(response: dict): """ Lowers firsts letter of all keys in the dictionary given and returns the new dictionary. """ demisto.debug(f"lowering keys for response: {response}") return {decapitalize(key): value for (key, value) in response.items()} def decapitalize(s: str): """ Decapitalizes a given string. """ if not s: return s demisto.debug(f"de-capitalizing key: {s}") return s[0].lower() + s[1:] def paging_heading(page_number: str = None, page_size: str = None): if page_number or page_size: return ( "Showing" + (f" {page_size}" if page_size else "") + " results" + (f" from page {page_number}" if page_number else "") + ":\n" ) return "" def set_state(states: str = ""): states = argToList(states) for state in states: if state not in ALERT_STATES: raise DemistoException("State must be of: all, no_data, paused, alerting, ok, pending, unknown.") # if all is not the first state given, Grafana ignores it and returns only other states given if "all" in states: states = [] return states def calculate_fetch_start_time(last_fetch: str = None, first_fetch: str = FETCH_DEFAULT_TIME): parsed_date = dateparser.parse(first_fetch) assert parsed_date is not None first_fetch_datetime = parsed_date.replace(tzinfo=utc, microsecond=0) if last_fetch is None: return first_fetch_datetime parsed_date = dateparser.parse(last_fetch) assert parsed_date is not None, f"could not parse {last_fetch}" last_fetch = parsed_date.replace(tzinfo=utc, microsecond=0) return max(last_fetch, first_fetch_datetime) def filter_alerts_by_time(alerts: List[Dict[str, Any]], last_fetch: datetime): # ignoring microsecond because date_to_timestamp doesn't know how to handle it return [alert for alert in alerts if dateparser.parse(alert["newStateDate"]).replace(tzinfo=utc, microsecond=0) >= last_fetch] # type: ignore def filter_alerts_by_id(alerts: List[Dict[str, Any]], last_fetch: datetime, last_id_fetched: int): # only for alerts with the same newStateDate as last_fetch return [ alert for alert in alerts if dateparser.parse(alert["newStateDate"]).replace(tzinfo=utc, microsecond=0) != last_fetch # type: ignore or alert["id"] > last_id_fetched ] def reduce_incidents_to_limit(alerts: List[Dict[str, Any]], limit: int, last_fetch: datetime, last_id_fetched: int): incidents_count = min(limit, len(alerts)) # limit can't be 0 or less, but there could be no alerts at the wanted time if incidents_count > 0: alerts = alerts[:limit] last_fetched_alert = alerts[incidents_count - 1] new_state_date = dateparser.parse(last_fetched_alert["newStateDate"]) assert new_state_date is not None, f"could not parse {last_fetched_alert['newStateDate']}" last_fetch = new_state_date.replace(tzinfo=utc, microsecond=0) last_id_fetched = last_fetched_alert["id"] return last_fetch, last_id_fetched, alerts def parse_alerts(alerts: List[Dict[str, Any]], limit: int, last_fetch: datetime, last_id_fetched: int): alerts = filter_alerts_by_time(alerts, last_fetch) alerts = filter_alerts_by_id(alerts, last_fetch, last_id_fetched) # sorting alerts by date and then by id alerts.sort( key=lambda alert: ( dateparser.parse(alert["newStateDate"]).replace(tzinfo=utc), # type: ignore alert["id"], ) ) last_fetch, last_id_fetched, alerts = reduce_incidents_to_limit(alerts, limit, last_fetch, last_id_fetched) incidents: List[Dict[str, Any]] = [alert_to_incident(alert) for alert in alerts] return last_fetch, last_id_fetched, incidents def alert_to_incident(alert: Dict[str, Any]): alert["type"] = "Grafana Alert" incident = {"name": alert["name"], "occurred": alert["newStateDate"], "rawJSON": json.dumps(alert), "type": alert["type"]} return incident """ COMMAND FUNCTIONS """ def alerts_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: dashboard_id = argToList(args.get("dashboard_id", "")) panel_id = args.get("panel_id") query = args.get("name") state = set_state(args.get("state", "")) limit = args.get("limit") folder_id = argToList(args.get("folder_id", "")) dashboard_query = args.get("dashboard_name") dashboard_tag = argToList(args.get("dashboard_tag", "")) responses = client.alerts_list_request(dashboard_id, panel_id, query, state, limit, folder_id, dashboard_query, dashboard_tag) for response in responses: change_key(response, "dashboardSlug", "dashboardName") headers = ["id", "name", "state", "newStateDate", "panelId", "dashboardId", "dashboardUid", "dashboardName", "url"] command_results = CommandResults( outputs_prefix="Grafana.Alert", outputs_key_field="id", outputs=responses, raw_response=responses, readable_output=tableToMarkdown( "Existing Alerts:", responses, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["url"] ), ) return command_results def alert_pause_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_id = str(args.get("alert_id")) response = client.alert_pause_request(alert_id, True) response = change_key(response, "alertId", "id") command_results = CommandResults( outputs_prefix="Grafana.Alert", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown(f"Paused Alert {alert_id}:", response, removeNull=True, headerTransform=pascalToSpace), ) return command_results def alert_unpause_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_id = str(args.get("alert_id")) response = client.alert_pause_request(alert_id, False) response = change_key(response, "alertId", "id") command_results = CommandResults( outputs_prefix="Grafana.Alert", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown(f"Un-paused Alert {alert_id}:", response, removeNull=True, headerTransform=pascalToSpace), ) return command_results def alert_get_by_id_command(client: Client, args: Dict[str, Any]) -> CommandResults: alert_id = str(args.get("alert_id")) response = client.alert_get_by_id_request(alert_id) # output returns keys capitalized rather then with first lower case letter (as stated and should be) response = keys_to_lowercase(response) headers = [ "id", "version", "orgId", "dashboardId", "panelId", "name", "message", "severity", "state", "newStateDate", "stateChanges", "handler", "silenced", "frequency", "for", "created", "updated", ] command_results = CommandResults( outputs_prefix="Grafana.Alert", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f"Alert {alert_id} Results:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def users_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: page_size = args.get("page_size") page_number = args.get("page_number") query = args.get("query") response = client.users_search_request(page_size, page_number, query) headers = ["id", "email", "name", "login", "isAdmin", "isDisabled", "avatarUrl", "lastSeenAt", "lastSeenAtAge", "authLabels"] command_results = CommandResults( outputs_prefix="Grafana.User", outputs_key_field="id", outputs=response, raw_response=response, readable_output=paging_heading(page_number, page_size) + tableToMarkdown( "Existing Users:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"] ), ) return command_results def user_get_by_id_command(client: Client, args: Dict[str, Any]) -> CommandResults: user_id = str(args.get("user_id")) response = client.user_get_by_id_request(user_id) headers = [ "id", "email", "name", "login", "theme", "orgId", "isGrafanaAdmin", "isDisabled", "isExternal", "updatedAt", "createdAt", "avatarUrl", "authLabels", ] command_results = CommandResults( outputs_prefix="Grafana.User", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f"User {user_id} Results:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"], ), ) return command_results def users_teams_command(client: Client, args: Dict[str, Any]) -> CommandResults: user_id = str(args.get("user_id")) response = client.users_teams_request(user_id) output = {"id": user_id, "teams": response} headers = ["id", "orgId", "name", "email", "avatarUrl", "memberCount", "permission"] command_results = CommandResults( outputs_prefix="Grafana.User", outputs_key_field="id", outputs=output, raw_response=response, readable_output=tableToMarkdown( f"Teams For User {user_id}:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"], ), ) return command_results def users_organization_command(client: Client, args: Dict[str, Any]) -> CommandResults: user_id = str(args.get("user_id")) response = client.users_organization_request(user_id) output = {"id": user_id, "orgs": response} command_results = CommandResults( outputs_prefix="Grafana.User", outputs_key_field="id", outputs=output, raw_response=response, readable_output=tableToMarkdown( f"Organizations For User {user_id}:", response, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def user_update_command(client: Client, args: Dict[str, Any]) -> CommandResults: user_id = str(args.get("user_id")) email = args.get("email") name = args.get("name") login = args.get("login") theme = args.get("theme") # login\email is required if not login and not email: raise DemistoException("Login or email must be specified.") response = client.user_update_request(user_id, email, name, login, theme) command_results = CommandResults( readable_output=tableToMarkdown( f"Successfully Updated User {user_id}:", response, removeNull=True, headerTransform=pascalToSpace ) ) return command_results def annotation_create_command(client: Client, args: Dict[str, Any]) -> CommandResults: dashboard_id = arg_to_number(args.get("dashboard_id")) panel_id = arg_to_number(args.get("panel_id")) time_start = set_time_to_epoch_millisecond(args.get("time")) time_end = set_time_to_epoch_millisecond(args.get("time_end")) tags = argToList(args.get("tags", "")) text = str(args.get("text")) response = client.annotation_create_request(text, dashboard_id, panel_id, time_start, time_end, tags) command_results = CommandResults( outputs_prefix="Grafana.Annotation", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f'Successfully Created Annotation {response["id"]}:', response, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def teams_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: page_size = args.get("page_size") page_number = args.get("page_number") query = args.get("query") name = args.get("name") response = client.teams_search_request(page_size, page_number, query, name) headers = ["id", "orgId", "name", "email", "avatarUrl", "memberCount", "permission"] command_results = CommandResults( outputs_prefix="Grafana.Team", outputs_key_field="id", outputs=response, raw_response=response, readable_output=paging_heading(page_number, page_size) + tableToMarkdown( "Teams Search Results:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"], ), ) return command_results def team_get_by_id_command(client: Client, args: Dict[str, Any]) -> CommandResults: team_id = str(args.get("team_id")) response = client.team_get_by_id_request(team_id) headers = ["id", "orgId", "name", "email", "avatarUrl", "memberCount", "permission"] command_results = CommandResults( outputs_prefix="Grafana.Team", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f"Team {team_id} Results:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"], ), ) return command_results def team_members_command(client: Client, args: Dict[str, Any]) -> CommandResults: team_id = str(args.get("team_id")) response = client.team_members_request(team_id) headers = ["orgId", "teamId", "userId", "auth_module", "email", "name", "login", "avatarUrl", "labels", "permission"] output = {"id": team_id, "members": response} command_results = CommandResults( outputs_prefix="Grafana.Team", outputs_key_field="id", outputs=output, raw_response=response, readable_output=tableToMarkdown( f"Team {team_id} Members:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["avatarUrl"], ), ) return command_results def user_add_to_team_command(client: Client, args: Dict[str, Any]) -> CommandResults: team_id = str(args.get("team_id")) user_id = str(args.get("user_id")) response = client.user_add_to_team_request(team_id, user_id) command_results = CommandResults( readable_output=tableToMarkdown( f"Successfully Added User {user_id} to Team {team_id}:", response, removeNull=True, headerTransform=pascalToSpace ) ) return command_results def user_remove_from_team_command(client: Client, args: Dict[str, Any]) -> CommandResults: team_id = str(args.get("team_id")) user_id = str(args.get("user_id")) response = client.user_remove_from_team_request(team_id, user_id) command_results = CommandResults( readable_output=tableToMarkdown( f"Successfully Removed User {user_id} from Team {team_id}:", response, removeNull=True, headerTransform=pascalToSpace ) ) return command_results def team_add_command(client: Client, args: Dict[str, Any]) -> CommandResults: name = str(args.get("name")) email = args.get("email") org_id = args.get("org_id") response = client.team_add_request(name, email, org_id) output = change_key(dict(response), "teamId", "id") command_results = CommandResults( outputs_prefix="Grafana.Team", outputs_key_field="id", outputs=output, raw_response=response, readable_output=tableToMarkdown( f'Successfully Created Team {response["teamId"]}:', response, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def team_delete_command(client: Client, args: Dict[str, Any]) -> CommandResults: team_id = str(args.get("team_id")) response = client.team_delete_request(team_id) command_results = CommandResults( readable_output=tableToMarkdown( f"Successfully Deleted Team {team_id}:", response, removeNull=True, headerTransform=pascalToSpace ) ) return command_results def org_create_command(client: Client, args: Dict[str, Any]) -> CommandResults: name = str(args.get("name")) response = client.org_create_request(name) output = change_key(dict(response), "orgId", "id") command_results = CommandResults( outputs_prefix="Grafana.Organization", outputs_key_field="id", outputs=output, raw_response=response, readable_output=tableToMarkdown( f'Successfully Created Organization {response["orgId"]}:', response, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def org_list_command(client: Client, args: Dict[str, Any]) -> CommandResults: page_size = args.get("page_size") page_number = args.get("page_number") # reply doesn't show this and total response = client.org_list_request(page_size, page_number) command_results = CommandResults( outputs_prefix="Grafana.Organization", outputs_key_field="id", outputs=response, raw_response=response, readable_output=paging_heading(page_number, page_size) + tableToMarkdown("Existing Organizations:", response, removeNull=True, headerTransform=pascalToSpace), ) return command_results def org_get_by_name_command(client: Client, args: Dict[str, Any]) -> CommandResults: name = str(args.get("name")) response = client.org_get_by_name_request(name) headers = ["name", "id", "address"] command_results = CommandResults( outputs_prefix="Grafana.Organization", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f'Organization "{name}" Results:', response, headers=headers, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def org_get_by_id_command(client: Client, args: Dict[str, Any]) -> CommandResults: org_id = args.get("org_id") response = client.org_get_by_id_request(org_id) headers = ["id", "name", "address"] command_results = CommandResults( outputs_prefix="Grafana.Organization", outputs_key_field="id", outputs=response, raw_response=response, readable_output=tableToMarkdown( f"Organization {org_id} Results:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace ), ) return command_results def dashboards_search_command(client: Client, args: Dict[str, Any]) -> CommandResults: query = args.get("query") tag = argToList(args.get("tag", "")) type_ = args.get("type") dashboard_ids = argToList(args.get("dashboard_ids", "")) folder_ids = argToList(args.get("folder_ids", "")) starred = args.get("starred") limit = args.get("limit") page_number = args.get("page_number") response = client.dashboards_search_request(query, tag, type_, dashboard_ids, folder_ids, starred, limit, page_number) headers = ["id", "uid", "title", "isStarred", "tags", "uri", "url", "slug", "type"] command_results = CommandResults( outputs_prefix="Grafana.Dashboard", outputs_key_field="id", outputs=response, raw_response=response, readable_output=paging_heading(page_number, limit) + tableToMarkdown( "Existing Dashboards:", response, headers=headers, removeNull=True, headerTransform=pascalToSpace, url_keys=["url"] ), ) return command_results def test_module(client: Client, params: dict) -> None: message: str = "" try: if client.users_search_request(): message = "ok" if params["isFetch"]: max_fetch = arg_to_number(params.get("max_fetch")) if max_fetch is not None and (max_fetch > MAX_INCIDENTS_TO_FETCH or max_fetch <= 0): raise DemistoException( f"Maximum number of incidents to fetch exceeds the limit " f"(restricted to {MAX_INCIDENTS_TO_FETCH}), or is below zero." ) client.alerts_list_request( dashboard_id=argToList(params.get("dashboard_id")), panel_id=params.get("panel_id"), query=params.get("alert_name"), state=params.get("state"), ) except DemistoException as e: if "Unauthorized" in str(e): message = "Authorization Error: make sure username and password are correctly set" else: raise e return return_results(message) def fetch_incidents( client: Client, first_fetch: str, dashboard_id: str = None, panel_id: str = None, alert_name: str = None, state: str = None, limit: Optional[int] = MAX_INCIDENTS_TO_FETCH, ) -> List[dict]: limit = limit or MAX_INCIDENTS_TO_FETCH last_fetch = demisto.getLastRun().get("last_fetch") last_id_fetched = demisto.getLastRun().get("last_id_fetched", -1) fetch_start_time = calculate_fetch_start_time(last_fetch, first_fetch) demisto.debug( f"last fetch was at: {last_fetch}, last id fetched was: {last_id_fetched}, time to fetch from is: {fetch_start_time}" ) alerts = client.alerts_list_request( dashboard_id=argToList(dashboard_id), panel_id=panel_id, query=alert_name, state=argToList(state) ) last_fetch, last_id_fetched, incidents = parse_alerts(alerts, limit, fetch_start_time, last_id_fetched) demisto.debug( f"last fetch now is: {last_fetch}, last id fetched is now: {last_id_fetched}, " f"number of incidents fetched is {len(incidents)}, number of alerts got is {len(alerts)}" ) demisto.setLastRun({"last_fetch": str(date_to_timestamp(last_fetch, DATE_FORMAT)), "last_id_fetched": last_id_fetched}) return incidents """ MAIN FUNCTION """ def main(): """main function, parses params and runs command functions""" params = demisto.params() args = demisto.args() url = params["url"] verify_certificate = not params.get("insecure", False) proxy = params.get("proxy", False) username = params["credentials"]["identifier"] password = params["credentials"]["password"] # we chose to use only Basic authentication, even though in some requests a Bearer authentication is documented # and is enough, because for some other queries Basic authentication is required command = demisto.command() demisto.debug(f"Command being called is {command}") try: urllib3.disable_warnings() client = Client(urljoin(url, ""), verify_certificate, proxy, headers=HEADERS, auth=(username, password)) commands = { "grafana-alerts-list": alerts_list_command, "grafana-alert-pause": alert_pause_command, "grafana-alert-unpause": alert_unpause_command, "grafana-alert-get-by-id": alert_get_by_id_command, "grafana-users-search": users_search_command, "grafana-user-get-by-id": user_get_by_id_command, "grafana-user-teams-get": users_teams_command, "grafana-user-orgs-get": users_organization_command, "grafana-user-update": user_update_command, "grafana-annotation-create": annotation_create_command, "grafana-teams-search": teams_search_command, "grafana-team-get-by-id": team_get_by_id_command, "grafana-team-members-list": team_members_command, "grafana-user-add-to-team": user_add_to_team_command, "grafana-user-remove-from-team": user_remove_from_team_command, "grafana-team-add": team_add_command, "grafana-team-delete": team_delete_command, "grafana-org-create": org_create_command, "grafana-org-list": org_list_command, "grafana-org-get-by-name": org_get_by_name_command, "grafana-org-get-by-id": org_get_by_id_command, "grafana-dashboards-search": dashboards_search_command, } if command == "fetch-incidents": first_fetch = params.get("first_fetch", FETCH_DEFAULT_TIME) dashboard_id = params.get("dashboard_id") panel_id = params.get("panel_id") alert_name = params.get("alert_name") state = params.get("state") limit = arg_to_number(params.get("max_fetch")) incidents = fetch_incidents(client, first_fetch, dashboard_id, panel_id, alert_name, state, limit) demisto.incidents(incidents) elif command == "test-module": test_module(client, params) elif command in commands: return_results(commands[command](client, args)) else: raise NotImplementedError(f"{command} command is not implemented.") except Exception as e: return_error(str(e)) """ ENTRY POINT """ if __name__ in ["__main__", "builtin", "builtins"]: main()