Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Logos/Miro.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[
{
"name": "MiroAuditLogsDCR",
"apiVersion": "2024-03-11",
"type": "Microsoft.Insights/dataCollectionRules",
"location": "{{location}}",
"properties": {
"streamDeclarations": {
"Custom-MiroAuditLogs_CL": {
"columns": [
{
"name": "id",
"type": "string"
},
{
"name": "event",
"type": "string"
},
{
"name": "category",
"type": "string"
},
{
"name": "type",
"type": "string"
},
{
"name": "createdAt",
"type": "string"
},
{
"name": "createdBy",
"type": "dynamic"
},
{
"name": "context",
"type": "dynamic"
},
{
"name": "details",
"type": "dynamic"
},
{
"name": "object",
"type": "dynamic"
}
]
}
},
"dataSources": {},
"destinations": {
"logAnalytics": [
{
"workspaceResourceId": "{{workspaceResourceId}}",
"name": "clv2ws1"
}
]
},
"dataFlows": [
{
"streams": [
"Custom-MiroAuditLogs_CL"
],
"destinations": [
"clv2ws1"
],
"transformKql": "source\n| extend TimeGenerated = todatetime(createdAt)\n| extend createdAt = todatetime(createdAt)\n| extend logType = type\n| extend createdBy_email = iff(isnull(createdBy), \"\", tostring(createdBy.email))\n| extend createdBy_id = iff(isnull(createdBy), \"\", tostring(createdBy.id))\n| extend createdBy_name = iff(isnull(createdBy), \"\", tostring(createdBy.name))\n| extend createdBy_type = iff(isnull(createdBy), \"\", tostring(createdBy.type))\n| extend object_id = iff(isnull(object), \"\", tostring(object.id))\n| extend object_name = iff(isnull(object), \"\", tostring(object.name))\n| extend context_ip = iff(isnull(context), \"\", tostring(context.ip))\n| extend context_team_id = iff(isnull(context.team), \"\", tostring(context.team.id))\n| extend context_team_name = iff(isnull(context.team), \"\", tostring(context.team.name))\n| extend context_team_type = iff(isnull(context.team), \"\", tostring(context.team.type))\n| extend context_organization_id = iff(isnull(context.organization), \"\", tostring(context.organization.id))\n| extend context_organization_name = iff(isnull(context.organization), \"\", tostring(context.organization.name))\n| extend context_organization_type = iff(isnull(context.organization), \"\", tostring(context.organization.type))\n| project TimeGenerated, id, createdAt, event, category, logType, createdBy_email, createdBy_id, createdBy_name, createdBy_type, object_id, object_name, context_ip, context_team_id, context_team_name, context_team_type, context_organization_id, context_organization_name, context_organization_type, details",
"outputStream": "Custom-MiroAuditLogs_CL"
}
],
"dataCollectionEndpointId": "[concat('/subscriptions/',variables('subscriptionID'),'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Insights/dataCollectionEndpoints/',{{dataCollectionEndpointId}}"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"name": "MiroAuditLogsDataConnector",
"apiVersion": "2025-09-01",
"type": "Microsoft.SecurityInsights/dataConnectorDefinitions",
"location": "{{location}}",
"kind": "Customizable",
"properties": {
"connectorUiConfig": {
"id": "MiroAuditLogsDataConnector",
"title": "Miro Audit Logs (Enterprise Plan)",
"publisher": "Miro",
"descriptionMarkdown": "The [Miro Audit Logs](https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs) data connector enables you to ingest organization-wide audit events from Miro into Microsoft Sentinel. Monitor user activities, security events, content access, team changes, and administrative actions to enhance your security operations and compliance capabilities.\n\n**Key features:**\n- Track user authentication and access patterns.\n- Monitor content creation, sharing, and deletion.\n- Audit team and organization configuration changes.\n- Detect suspicious activities and policy violations.\n- Meet compliance and regulatory requirements.\n\n**Requirements:**\n- **Miro Plan**: [Enterprise Plan](https://miro.com/pricing/).\n- **OAuth scope**: `auditlogs:read`.\n- **Role**: Company Admin in your Miro organization.\n\n💡 **Not on Enterprise Plan yet?** Upgrade to [Miro Enterprise](https://miro.com/enterprise/) to unlock audit logs and gain comprehensive visibility into your team's activities in Microsoft Sentinel.\n\nFor detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).",
"graphQueriesTableName": "MiroAuditLogs_CL",
"graphQueries": [
{
"metricName": "Miro Audit Logs",
"legend": "MiroAuditLogs_CL",
"baseQuery": "MiroAuditLogs_CL"
}
],
"sampleQueries": [
{
"description": "Recent audit events",
"query": "MiroAuditLogs_CL\n| sort by TimeGenerated desc\n| take 10"
},
{
"description": "Events by category",
"query": "MiroAuditLogs_CL\n| summarize count() by category\n| render piechart"
}
],
"dataTypes": [
{
"name": "MiroAuditLogs_CL",
"lastDataReceivedQuery": "MiroAuditLogs_CL\n| summarize Time = max(TimeGenerated)\n| where isnotempty(Time)"
}
],
"availability": {
"isPreview": false
},
"connectivityCriteria": [
{
"type": "HasDataConnectors"
}
],
"permissions": {
"resourceProvider": [
{
"provider": "Microsoft.OperationalInsights/workspaces",
"permissionsDisplayText": "Read and Write permissions are required.",
"providerDisplayName": "Workspace",
"scope": "Workspace",
"requiredPermissions": {
"write": true,
"read": true,
"delete": true
}
}
],
"customs": [
{
"name": "Miro Enterprise Plan",
"description": "Miro Enterprise Plan subscription is required."
},
{
"name": "Miro OAuth Application",
"description": "Miro OAuth application with auditlogs:read scope and Company Admin role is required."
}
]
},
"instructionSteps": [
{
"description": "**Step 1: Verify your Miro plan**\n\n1. Ensure your organization has an active [Miro Enterprise Plan](https://miro.com/pricing/).\n2. If you need to upgrade, contact [Miro Sales](https://miro.com/contact/sales/) or your account manager.\n3. You must be a **Company Admin** to set up this integration."
},
{
"description": "**Step 2: Choose your setup option**\n\nThere are two ways to set up the Miro Audit Logs connector.\n\n**Option 1 (recommended):** Use Enterprise integrations\n- Simplest setup with automatic token generation.\n- Recommended for most users.\n- See Option 1 below.\n\n**Option 2 (alternative):** Create custom OAuth application\n- More control over OAuth app configuration.\n- For advanced users or custom integration needs.\n- See Option 2 below.\n\n**Note:** When using Option 1, the integration is automatically tied to the team with the largest number of users in your organization. When using Option 2, you can choose which team to install the app to. However, **the team selection does not affect which logs are collected**—both options provide organization-wide log access. All integration-relevant events from all teams are included in your logs."
},
{
"description": "**Option 1: Enterprise integrations (recommended)**\n\n1. Open [Miro Company Settings](https://miro.com/app/settings/).\n2. Expand the **Apps and integrations** section.\n3. Click **Enterprise integrations**.\n4. Enable the **SIEM** toggle.\n5. Copy the **Access Token** value that appears.\n6. **Important:** Store the token securely—it provides full access to audit logs.\n7. The token will work until you disable the toggle.\n8. Proceed to Step 3."
},
{
"description": "**Option 2: Custom OAuth application (alternative)**\n\n1. Go to [Miro App Settings](https://miro.com/app/settings/user-profile/apps).\n2. Click **Create new app**.\n3. Select **Non-expiring access token** option during app creation.\n4. Enable the OAuth scope: **`auditlogs:read`**.\n5. Click **Install app and get OAuth token**.\n6. Authorize the app to access your organization.\n7. Copy the **Access Token** that is displayed.\n8. **Important:** Store the token securely—it provides full access to audit logs.\n9. The token will work until you uninstall the app."
},
{
"description": "**Step 3: Learn more**\n\nFor detailed information about Miro audit logs:\n- [Miro Audit Logs documentation](https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs)\n- [Miro API reference](https://developers.miro.com/reference/enterprise-get-audit-logs)\n- [OAuth non-expiring tokens](https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens)\n- [Enterprise integrations settings](https://miro.com/app/settings/)"
},
{
"description": "**Step 4: Connect to Miro**\n\nProvide your Miro access token below to complete the connection.",
"instructions": [
{
"type": "Textbox",
"parameters": {
"label": "Access token",
"placeholder": "Enter your Miro Access Token",
"type": "password",
"name": "AccessToken"
}
},
{
"type": "ConnectionToggleButton",
"parameters": {
"label": "toggle",
"name": "toggle"
}
}
],
"title": "Connect to Miro to start collecting audit logs in Microsoft Sentinel."
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"name": "MiroAuditLogsPoller",
"apiVersion": "2025-09-01",
"type": "Microsoft.SecurityInsights/dataConnectors",
"location": "{{location}}",
"kind": "RestApiPoller",
"properties": {
"connectorDefinitionName": "MiroAuditLogsDataConnector",
"dcrConfig": {
"dataCollectionEndpoint": "{{dataCollectionEndpoint}}",
"dataCollectionRuleImmutableId": "{{auditLogsDataCollectionRuleImmutableId}}",
"streamName": "Custom-MiroAuditLogs_CL"
},
"dataType": "Miro Audit Logs",
"response": {
"eventsJsonPaths": [
"$.data"
],
"format": "json"
},
"paging": {
"pagingType": "NextPageToken",
"nextPageTokenJsonPath": "$.cursor",
"nextPageParaName": "cursor",
"pageSize": 100
},
"auth": {
"type": "APIKey",
"ApiKeyName": "Authorization",
"APIKey": "Bearer {{AccessToken}}",
"IsAPIKeyInPostPayload": false
},
"request": {
"apiEndpoint": "https://api.miro.com/v2/audit/logs",
"rateLimitQPS": 10,
"queryWindowInMin": 5,
"queryTimeFormat": "yyyy-MM-dd'T'HH:mm:ss'.00Z'",
"httpMethod": "GET",
"retryCount": 3,
"timeoutInSeconds": 60,
"headers": {
"Accept": "application/json",
"User-Agent": "Microsoft-Azure-Sentinel-MiroAuditLogsDataConnector"
},
"StartTimeAttributeName": "createdAfter",
"EndTimeAttributeName": "createdBefore",
"queryParameters": {
"createdAfter": "{_QueryWindowStartTime}",
"createdBefore": "{_QueryWindowEndTime}",
"sorting": "ASC",
"limit": "100"
}
},
"isActive": true
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"name": "MiroAuditLogs_CL",
"apiVersion": "2025-07-01",
"type": "Microsoft.OperationalInsights/workspaces/tables",
"location": "{{location}}",
"kind": null,
"properties": {
"schema": {
"name": "MiroAuditLogs_CL",
"columns": [
{
"name": "TimeGenerated",
"type": "datetime",
"description": "The timestamp (UTC) reflecting the time when the event was ingested"
},
{
"name": "id",
"type": "string",
"description": "Unique identifier of the audit event"
},
{
"name": "createdAt",
"type": "datetime",
"description": "Timestamp when the audit event was created"
},
{
"name": "event",
"type": "string",
"description": "Name of the audit event"
},
{
"name": "category",
"type": "string",
"description": "Category of the audit event"
},
{
"name": "logType",
"type": "string",
"description": "Type of the log entry. Mapped from API's 'type' field to avoid reserved 'Type' column name."
},
{
"name": "createdBy_email",
"type": "string",
"description": "Email address of the user who triggered the event"
},
{
"name": "createdBy_id",
"type": "string",
"description": "Unique identifier of the user who triggered the event"
},
{
"name": "createdBy_name",
"type": "string",
"description": "Name of the user who triggered the event"
},
{
"name": "createdBy_type",
"type": "string",
"description": "Type of the actor (user, service account, etc.)"
},
{
"name": "object_id",
"type": "string",
"description": "Unique identifier of the object affected by the event"
},
{
"name": "object_name",
"type": "string",
"description": "Name of the object affected by the event"
},
{
"name": "context_ip",
"type": "string",
"description": "IP address from which the event originated"
},
{
"name": "context_team_id",
"type": "string",
"description": "Unique identifier of the team context"
},
{
"name": "context_team_name",
"type": "string",
"description": "Name of the team context"
},
{
"name": "context_team_type",
"type": "string",
"description": "Type of the team"
},
{
"name": "context_organization_id",
"type": "string",
"description": "Unique identifier of the organization"
},
{
"name": "context_organization_name",
"type": "string",
"description": "Name of the organization"
},
{
"name": "context_organization_type",
"type": "string",
"description": "Type of the organization"
},
{
"name": "details",
"type": "dynamic",
"description": "Additional event details in JSON format"
}
]
}
}
}
Loading
Loading