From 481af13e958b9a73e01894bbb9429a45c9f9b5a8 Mon Sep 17 00:00:00 2001 From: Ilia Sretenskii Date: Thu, 4 Dec 2025 15:03:51 +0400 Subject: [PATCH 1/5] Add Miro solution v3.0.0 for Microsoft Sentinel Adds Miro solution with two CCF data connectors for ingesting Miro audit logs and content activity logs into Microsoft Sentinel. Components: - Miro Audit Logs connector (Enterprise Plan) - Miro Content Logs connector (Enterprise Plan + Enterprise Guard) - Solution metadata with 7 domain categories - Data collection rules and custom tables - ARM templates for deployment - README.md with installation and configuration guide - ReleaseNotes.md for version 3.0.0 --- .../MiroAuditLogs_CCF/MiroAuditLogs_DCR.json | 74 + ...MiroAuditLogs_DataConnectorDefinition.json | 111 ++ .../MiroAuditLogs_PollingConfig.json | 58 + .../MiroAuditLogs_Table.json | 114 ++ .../MiroContentLogs_DCR.json | 74 + ...roContentLogs_DataConnectorDefinition.json | 128 ++ .../MiroContentLogs_PollingConfig.json | 61 + .../MiroContentLogs_Table.json | 74 + Solutions/Miro/Data/Solution_Miro.json | 14 + Solutions/Miro/Logo/Miro.svg | 4 + Solutions/Miro/Package/3.0.0.zip | Bin 0 -> 12499 bytes .../Miro/Package/createUiDefinition.json | 102 ++ Solutions/Miro/Package/mainTemplate.json | 1514 +++++++++++++++++ Solutions/Miro/Package/testParameters.json | 38 + Solutions/Miro/README.md | 266 +++ Solutions/Miro/ReleaseNotes.md | 3 + Solutions/Miro/SolutionMetadata.json | 22 + 17 files changed, 2657 insertions(+) create mode 100644 Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DCR.json create mode 100644 Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json create mode 100644 Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_PollingConfig.json create mode 100644 Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_Table.json create mode 100644 Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DCR.json create mode 100644 Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DataConnectorDefinition.json create mode 100644 Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_PollingConfig.json create mode 100644 Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_Table.json create mode 100644 Solutions/Miro/Data/Solution_Miro.json create mode 100644 Solutions/Miro/Logo/Miro.svg create mode 100644 Solutions/Miro/Package/3.0.0.zip create mode 100644 Solutions/Miro/Package/createUiDefinition.json create mode 100644 Solutions/Miro/Package/mainTemplate.json create mode 100644 Solutions/Miro/Package/testParameters.json create mode 100644 Solutions/Miro/README.md create mode 100644 Solutions/Miro/ReleaseNotes.md create mode 100644 Solutions/Miro/SolutionMetadata.json diff --git a/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DCR.json b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DCR.json new file mode 100644 index 00000000000..68055ff7d19 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DCR.json @@ -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}}" + } + } +] diff --git a/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json new file mode 100644 index 00000000000..b7eeba3fa5c --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json @@ -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." + } + ] + } + } +} diff --git a/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_PollingConfig.json b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_PollingConfig.json new file mode 100644 index 00000000000..e659cc20805 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_PollingConfig.json @@ -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 + } + } +] diff --git a/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_Table.json b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_Table.json new file mode 100644 index 00000000000..9ebf5133845 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_Table.json @@ -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" + } + ] + } + } +} diff --git a/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DCR.json b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DCR.json new file mode 100644 index 00000000000..24af0701410 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DCR.json @@ -0,0 +1,74 @@ +[ + { + "name": "MiroContentLogsDCR", + "apiVersion": "2024-03-11", + "type": "Microsoft.Insights/dataCollectionRules", + "location": "{{location}}", + "properties": { + "streamDeclarations": { + "Custom-MiroContentLogs_CL": { + "columns": [ + { + "name": "id", + "type": "string" + }, + { + "name": "contentId", + "type": "string" + }, + { + "name": "actionType", + "type": "string" + }, + { + "name": "actionTime", + "type": "string" + }, + { + "name": "actor", + "type": "dynamic" + }, + { + "name": "itemType", + "type": "string" + }, + { + "name": "itemId", + "type": "string" + }, + { + "name": "state", + "type": "dynamic" + }, + { + "name": "relationships", + "type": "dynamic" + } + ] + } + }, + "dataSources": {}, + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "{{workspaceResourceId}}", + "name": "clv2ws1" + } + ] + }, + "dataFlows": [ + { + "streams": [ + "Custom-MiroContentLogs_CL" + ], + "destinations": [ + "clv2ws1" + ], + "transformKql": "source\n| extend TimeGenerated = todatetime(actionTime)\n| extend actionTime = todatetime(actionTime)\n| extend actor_id = iff(isnull(actor), \"\", tostring(actor.id))\n| extend actor_email = iff(isnull(actor), \"\", tostring(actor.email))\n| extend actor_name = iff(isnull(actor), \"\", tostring(actor.name))\n| project TimeGenerated, id, actionTime, actionType, actor_id, actor_email, actor_name, contentId, itemId, itemType, relationships, state", + "outputStream": "Custom-MiroContentLogs_CL" + } + ], + "dataCollectionEndpointId": "[concat('/subscriptions/',variables('subscriptionID'),'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Insights/dataCollectionEndpoints/',{{dataCollectionEndpointId}}" + } + } +] diff --git a/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DataConnectorDefinition.json b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DataConnectorDefinition.json new file mode 100644 index 00000000000..604afc901c6 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DataConnectorDefinition.json @@ -0,0 +1,128 @@ +{ + "name": "MiroContentLogsDataConnector", + "apiVersion": "2025-09-01", + "type": "Microsoft.SecurityInsights/dataConnectorDefinitions", + "location": "{{location}}", + "kind": "Customizable", + "properties": { + "connectorUiConfig": { + "id": "MiroContentLogsDataConnector", + "title": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "publisher": "Miro", + "descriptionMarkdown": "The [Miro Content Logs](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview) data connector enables you to ingest content activity logs from Miro into Microsoft Sentinel. Part of Miro's Enterprise Guard eDiscovery capabilities, this connector provides content-level visibility for compliance, legal hold, and advanced threat detection.\n\n**Key features:**\n- Track all content item changes.\n- Monitor content modifications by user and timestamp.\n- Support compliance and eDiscovery requirements.\n- Detect data exfiltration and insider threats.\n- Meet regulatory and legal hold obligations.\n\n**Requirements:**\n- **Miro Plan**: [Enterprise Plan](https://miro.com/pricing/) + **Enterprise Guard** add-on.\n- **OAuth scope**: `contentlogs:export`.\n- **Role**: Company Admin in your Miro organization.\n- **Organization ID**: Your Miro organization identifier.\n\n💡 **Not on Enterprise Plan yet?** Upgrade to [Miro Enterprise](https://miro.com/enterprise/) to unlock advanced security and compliance features for your team's collaboration activities in Microsoft Sentinel.\n\n💡 **Need Content Logs?** Content activity logging is part of [Miro Enterprise Guard](https://miro.com/enterprise-guard/), which provides advanced security, compliance, and eDiscovery features. Contact your Miro account manager to add Enterprise Guard to your Enterprise Plan and unlock content-level monitoring in Microsoft Sentinel.\n\n**Note:** If you only have the base Enterprise Plan (without Enterprise Guard), please use the **Miro Audit Logs** connector instead for organization-level event monitoring.\n\nFor detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).", + "graphQueriesTableName": "MiroContentLogs_CL", + "graphQueries": [ + { + "metricName": "Miro Content Logs", + "legend": "MiroContentLogs_CL", + "baseQuery": "MiroContentLogs_CL" + } + ], + "sampleQueries": [ + { + "description": "Recent content changes", + "query": "MiroContentLogs_CL\n| sort by TimeGenerated desc\n| take 10" + }, + { + "description": "Activity by action type", + "query": "MiroContentLogs_CL\n| summarize count() by actionType\n| render piechart" + }, + { + "description": "Most active users", + "query": "MiroContentLogs_CL\n| summarize events = count() by actor_name\n| top 10 by events desc" + } + ], + "dataTypes": [ + { + "name": "MiroContentLogs_CL", + "lastDataReceivedQuery": "MiroContentLogs_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 with Enterprise Guard", + "description": "Miro Enterprise Plan with Enterprise Guard add-on is required. Content logs are part of Miro's eDiscovery features and are not available on base Enterprise Plan or lower tiers." + }, + { + "name": "Miro OAuth Application", + "description": "Miro OAuth application with contentlogs:export scope and Company Admin role is required." + }, + { + "name": "Miro Organization ID", + "description": "Your Miro organization ID is required to access content logs." + } + ] + }, + "instructionSteps": [ + { + "description": "**Step 1: Verify your Miro plan and Enterprise Guard**\n\n1. Ensure your organization has [Miro Enterprise Plan](https://miro.com/pricing/) with **Enterprise Guard** add-on.\n2. Content logs are part of Miro's eDiscovery (Enterprise Guard) features.\n3. If you don't have Enterprise Guard yet, contact your [Miro account manager](https://miro.com/contact/sales/) to upgrade.\n4. Without Enterprise Guard, use the **Miro Audit Logs** connector for organization-level monitoring.\n5. 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 Content 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 **eDiscovery** toggle.\n5. Copy the **Access Token** value that appears.\n6. Get your **Organization ID** from the browser URL:\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n7. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n8. The token will work until you disable the toggle.\n9. 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: **`contentlogs:export`**.\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. Get your **Organization ID**:\n - Go to [Miro Company Settings](https://miro.com/app/settings/).\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n9. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n10. The token will work until you uninstall the app." + }, + { + "description": "**Step 3: Learn more**\n\nFor detailed information about Miro content logs and eDiscovery:\n- [Miro Content Logs overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview)\n- [Miro Enterprise Guard](https://miro.com/enterprise-guard/)\n- [Miro API reference](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch)\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 the required values below to complete the connection.", + "instructions": [ + { + "type": "Textbox", + "parameters": { + "label": "Organization ID", + "placeholder": "Enter your Miro Organization ID", + "type": "text", + "name": "organizationId" + } + }, + { + "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 content logs in Microsoft Sentinel." + } + ] + } + } +} diff --git a/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_PollingConfig.json b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_PollingConfig.json new file mode 100644 index 00000000000..a93d0343970 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_PollingConfig.json @@ -0,0 +1,61 @@ +[ + { + "name": "MiroContentLogsPoller", + "apiVersion": "2025-09-01", + "type": "Microsoft.SecurityInsights/dataConnectors", + "location": "{{location}}", + "kind": "RestApiPoller", + "properties": { + "connectorDefinitionName": "MiroContentLogsDataConnector", + "dcrConfig": { + "dataCollectionEndpoint": "{{dataCollectionEndpoint}}", + "dataCollectionRuleImmutableId": "{{contentLogsDataCollectionRuleImmutableId}}", + "streamName": "Custom-MiroContentLogs_CL" + }, + "dataType": "Miro Content Logs", + "addOnAttributes": { + "OrganizationId": "[[parameters('organizationId')]" + }, + "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/orgs/{{organizationId}}/content-logs/items", + "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-MiroContentLogsDataConnector" + }, + "StartTimeAttributeName": "from", + "EndTimeAttributeName": "to", + "queryParameters": { + "from": "{_QueryWindowStartTime}", + "to": "{_QueryWindowEndTime}", + "sorting": "asc", + "limit": "100" + } + }, + "isActive": true + } + } +] diff --git a/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_Table.json b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_Table.json new file mode 100644 index 00000000000..8a099ebf656 --- /dev/null +++ b/Solutions/Miro/Data Connectors/MiroContentLogs_CCF/MiroContentLogs_Table.json @@ -0,0 +1,74 @@ +{ + "name": "MiroContentLogs_CL", + "apiVersion": "2025-07-01", + "type": "Microsoft.OperationalInsights/workspaces/tables", + "location": "{{location}}", + "kind": null, + "properties": { + "schema": { + "name": "MiroContentLogs_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 content log event" + }, + { + "name": "actionTime", + "type": "datetime", + "description": "Timestamp when the action was performed" + }, + { + "name": "actionType", + "type": "string", + "description": "Type of action performed (create, update, delete, etc.)" + }, + { + "name": "actor_id", + "type": "string", + "description": "Unique identifier of the user who performed the action" + }, + { + "name": "actor_email", + "type": "string", + "description": "Email address of the user who performed the action" + }, + { + "name": "actor_name", + "type": "string", + "description": "Name of the user who performed the action" + }, + { + "name": "contentId", + "type": "string", + "description": "Unique identifier of the content affected" + }, + { + "name": "itemId", + "type": "string", + "description": "Unique identifier of the item affected" + }, + { + "name": "itemType", + "type": "string", + "description": "Type of the content item" + }, + { + "name": "relationships", + "type": "dynamic", + "description": "Relationships of the content item in JSON format" + }, + { + "name": "state", + "type": "dynamic", + "description": "State information of the content item in JSON format" + } + ] + } + } +} diff --git a/Solutions/Miro/Data/Solution_Miro.json b/Solutions/Miro/Data/Solution_Miro.json new file mode 100644 index 00000000000..90e89d1aee7 --- /dev/null +++ b/Solutions/Miro/Data/Solution_Miro.json @@ -0,0 +1,14 @@ +{ + "Name": "Miro", + "Author": "Miro - enterprise_integrations@miro.com", + "Logo": "", + "Description": "The [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).\n\n**Underlying Microsoft technology used:**\n\nThis solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\n• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector)", + "Data Connectors": [ + "Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json", + "Data Connectors/MiroContentLogs_CCF/MiroContentLogs_DataConnectorDefinition.json" + ], + "Version": "3.0.0", + "Metadata": "SolutionMetadata.json", + "TemplateSpec": true, + "Is1PConnector": false +} diff --git a/Solutions/Miro/Logo/Miro.svg b/Solutions/Miro/Logo/Miro.svg new file mode 100644 index 00000000000..169efff82ec --- /dev/null +++ b/Solutions/Miro/Logo/Miro.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Solutions/Miro/Package/3.0.0.zip b/Solutions/Miro/Package/3.0.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..0cdf3c2c4ba8c1cca08897fbd0ab76d068d57778 GIT binary patch literal 12499 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 literal 0 HcmV?d00001 diff --git a/Solutions/Miro/Package/createUiDefinition.json b/Solutions/Miro/Package/createUiDefinition.json new file mode 100644 index 00000000000..fd3ca5c726f --- /dev/null +++ b/Solutions/Miro/Package/createUiDefinition.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#", + "handler": "Microsoft.Azure.CreateUIDef", + "version": "0.1.2-preview", + "parameters": { + "config": { + "isWizard": false, + "basics": { + "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Miro/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).\n\n**Underlying Microsoft technology used:**\n\nThis solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\n• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector)\n\n**Data Connectors:** 2\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "subscription": { + "resourceProviders": [ + "Microsoft.OperationsManagement/solutions", + "Microsoft.OperationalInsights/workspaces/providers/alertRules", + "Microsoft.Insights/workbooks", + "Microsoft.Logic/workflows" + ] + }, + "location": { + "metadata": { + "hidden": "Hiding location, we get it from the log analytics workspace" + }, + "visible": false + }, + "resourceGroup": { + "allowExisting": true + } + } + }, + "basics": [ + { + "name": "getLAWorkspace", + "type": "Microsoft.Solutions.ArmApiControl", + "toolTip": "This filters by workspaces that exist in the Resource Group selected", + "condition": "[greater(length(resourceGroup().name),0)]", + "request": { + "method": "GET", + "path": "[concat(subscription().id,'/providers/Microsoft.OperationalInsights/workspaces?api-version=2020-08-01')]" + } + }, + { + "name": "workspace", + "type": "Microsoft.Common.DropDown", + "label": "Workspace", + "placeholder": "Select a workspace", + "toolTip": "This dropdown will list only workspace that exists in the Resource Group selected", + "constraints": { + "allowedValues": "[map(filter(basics('getLAWorkspace').value, (filter) => contains(toLower(filter.id), toLower(resourceGroup().name))), (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.name, '\"}')))]", + "required": true + }, + "visible": true + } + ], + "steps": [ + { + "name": "dataconnectors", + "label": "Data Connectors", + "bladeTitle": "Data Connectors", + "elements": [ + { + "name": "dataconnectors1-text", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "This Solution installs the data connector for Miro Audit Logs (Enterprise Plan). You can get Miro Audit Logs (Enterprise Plan) data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." + } + }, + { + "name": "dataconnectors-link1", + "type": "Microsoft.Common.TextBlock", + "options": { + "link": { + "label": "Learn more about connecting data sources", + "uri": "https://docs.microsoft.com/azure/sentinel/connect-data-sources" + } + } + }, + { + "name": "dataconnectors2-text", + "type": "Microsoft.Common.TextBlock", + "options": { + "text": "This Solution installs the data connector for Miro Content Logs (Enterprise Plan + Enterprise Guard). You can get Miro Content Logs (Enterprise Plan + Enterprise Guard) data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." + } + }, + { + "name": "dataconnectors-link2", + "type": "Microsoft.Common.TextBlock", + "options": { + "link": { + "label": "Learn more about connecting data sources", + "uri": "https://docs.microsoft.com/azure/sentinel/connect-data-sources" + } + } + } + ] + } + ], + "outputs": { + "workspace-location": "[first(map(filter(basics('getLAWorkspace').value, (filter) => and(contains(toLower(filter.id), toLower(resourceGroup().name)),equals(filter.name,basics('workspace')))), (item) => item.location))]", + "location": "[location()]", + "workspace": "[basics('workspace')]" + } + } +} diff --git a/Solutions/Miro/Package/mainTemplate.json b/Solutions/Miro/Package/mainTemplate.json new file mode 100644 index 00000000000..078af27b5db --- /dev/null +++ b/Solutions/Miro/Package/mainTemplate.json @@ -0,0 +1,1514 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "author": "Miro - enterprise_integrations@miro.com", + "comments": "Solution template for Miro" + }, + "parameters": { + "location": { + "type": "string", + "minLength": 1, + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Not used, but needed to pass arm-ttk test `Location-Should-Not-Be-Hardcoded`. We instead use the `workspace-location` which is derived from the LA workspace" + } + }, + "workspace-location": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "[concat('Region to deploy solution resources -- separate from location selection',parameters('location'))]" + } + }, + "workspace": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "Workspace name for Log Analytics where Microsoft Sentinel is setup" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "resource group name where Microsoft Sentinel is setup" + } + }, + "subscription": { + "type": "string", + "defaultValue": "[last(split(subscription().id, '/'))]", + "metadata": { + "description": "subscription id where Microsoft Sentinel is setup" + } + } + }, + "variables": { + "email": "enterprise_integrations@miro.com", + "_email": "[variables('email')]", + "_solutionName": "Miro", + "_solutionVersion": "3.0.0", + "solutionId": "miro.azure-sentinel-solution-miro", + "_solutionId": "[variables('solutionId')]", + "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", + "dataConnectorCCPVersion": "1.0.0", + "_dataConnectorContentIdConnectorDefinition1": "MiroAuditLogsDataConnector", + "dataConnectorTemplateNameConnectorDefinition1": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentIdConnectorDefinition1')))]", + "_dataConnectorContentIdConnections1": "MiroAuditLogsDataConnectorConnections", + "dataConnectorTemplateNameConnections1": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentIdConnections1')))]", + "dataCollectionEndpointId1": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/dataCollectionEndpoints/',parameters('workspace'))]", + "blanks": "[replace('b', 'b', '')]", + "TemplateEmptyObject": "[json('{}')]", + "_dataConnectorContentIdConnectorDefinition2": "MiroContentLogsDataConnector", + "dataConnectorTemplateNameConnectorDefinition2": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentIdConnectorDefinition2')))]", + "_dataConnectorContentIdConnections2": "MiroContentLogsDataConnectorConnections", + "dataConnectorTemplateNameConnections2": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentIdConnections2')))]", + "dataCollectionEndpointId2": "[concat('/subscriptions/',parameters('subscription'),'/resourceGroups/',parameters('resourceGroupName'),'/providers/Microsoft.Insights/dataCollectionEndpoints/',parameters('workspace'))]", + "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('dataConnectorTemplateNameConnectorDefinition1'), variables('dataConnectorCCPVersion'))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition1')]", + "displayName": "Miro Audit Logs (Enterprise Plan)", + "contentKind": "DataConnector", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('dataConnectorCCPVersion')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentIdConnectorDefinition1'))]", + "apiVersion": "2022-09-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectorDefinitions", + "location": "[parameters('workspace-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." + } + ] + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnectorDefinition1')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectorDefinitions', variables('_dataConnectorContentIdConnectorDefinition1'))]", + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + }, + "dependencies": { + "criteria": [ + { + "version": "[variables('dataConnectorCCPVersion')]", + "contentId": "[variables('_dataConnectorContentIdConnections1')]", + "kind": "ResourcesDataConnector" + } + ] + } + } + }, + { + "name": "MiroAuditLogsDCR", + "apiVersion": "2022-06-01", + "type": "Microsoft.Insights/dataCollectionRules", + "location": "[parameters('workspace-location')]", + "kind": "[variables('blanks')]", + "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": "[variables('TemplateEmptyObject')]", + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[variables('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": "[variables('dataCollectionEndpointId1')]" + } + }, + { + "name": "MiroAuditLogs_CL", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/tables", + "location": "[parameters('workspace-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" + } + ] + } + } + }, + { + "name": "MiroContentLogs_CL", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/tables", + "location": "[parameters('workspace-location')]", + "kind": null, + "properties": { + "schema": { + "name": "MiroContentLogs_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 content log event" + }, + { + "name": "actionTime", + "type": "datetime", + "description": "Timestamp when the action was performed" + }, + { + "name": "actionType", + "type": "string", + "description": "Type of action performed (create, update, delete, etc.)" + }, + { + "name": "actor_id", + "type": "string", + "description": "Unique identifier of the user who performed the action" + }, + { + "name": "actor_email", + "type": "string", + "description": "Email address of the user who performed the action" + }, + { + "name": "actor_name", + "type": "string", + "description": "Name of the user who performed the action" + }, + { + "name": "contentId", + "type": "string", + "description": "Unique identifier of the content affected" + }, + { + "name": "itemId", + "type": "string", + "description": "Unique identifier of the item affected" + }, + { + "name": "itemType", + "type": "string", + "description": "Type of the content item" + }, + { + "name": "relationships", + "type": "dynamic", + "description": "Relationships of the content item in JSON format" + }, + { + "name": "state", + "type": "dynamic", + "description": "State information of the content item in JSON format" + } + ] + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "contentProductId": "[concat(take(variables('_solutionId'), 50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentIdConnectorDefinition1'),'-', variables('dataConnectorCCPVersion'))))]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "version": "[variables('dataConnectorCCPVersion')]" + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentIdConnectorDefinition1'))]", + "apiVersion": "2022-09-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectorDefinitions", + "location": "[parameters('workspace-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." + } + ] + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnectorDefinition1')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectorDefinitions', variables('_dataConnectorContentIdConnectorDefinition1'))]", + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + }, + "dependencies": { + "criteria": [ + { + "version": "[variables('dataConnectorCCPVersion')]", + "contentId": "[variables('_dataConnectorContentIdConnections1')]", + "kind": "ResourcesDataConnector" + } + ] + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('dataConnectorTemplateNameConnections1'), variables('dataConnectorCCPVersion'))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "contentId": "[variables('_dataConnectorContentIdConnections1')]", + "displayName": "Miro Audit Logs (Enterprise Plan)", + "contentKind": "ResourcesDataConnector", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('dataConnectorCCPVersion')]", + "parameters": { + "guidValue": { + "defaultValue": "[[newGuid()]", + "type": "securestring" + }, + "innerWorkspace": { + "defaultValue": "[parameters('workspace')]", + "type": "securestring" + }, + "connectorDefinitionName": { + "defaultValue": "Miro Audit Logs (Enterprise Plan)", + "type": "securestring", + "minLength": 1 + }, + "workspace": { + "defaultValue": "[parameters('workspace')]", + "type": "securestring" + }, + "dcrConfig": { + "defaultValue": { + "dataCollectionEndpoint": "data collection Endpoint", + "dataCollectionRuleImmutableId": "data collection rule immutableId" + }, + "type": "object" + }, + "AccessToken": { + "defaultValue": "AccessToken", + "type": "securestring", + "minLength": 1 + } + }, + "variables": { + "_dataConnectorContentIdConnections1": "[variables('_dataConnectorContentIdConnections1')]" + }, + "resources": [ + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnections1')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentIdConnections1'))]", + "contentId": "[variables('_dataConnectorContentIdConnections1')]", + "kind": "ResourcesDataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + } + } + }, + { + "name": "[[concat(parameters('innerWorkspace'),'/Microsoft.SecurityInsights/', 'MiroAuditLogsPoller', parameters('guidValue'))]", + "apiVersion": "2023-02-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "location": "[parameters('workspace-location')]", + "kind": "RestApiPoller", + "properties": { + "connectorDefinitionName": "MiroAuditLogsDataConnector", + "dcrConfig": { + "dataCollectionEndpoint": "[[parameters('dcrConfig').dataCollectionEndpoint]", + "dataCollectionRuleImmutableId": "[[parameters('dcrConfig').dataCollectionRuleImmutableId]", + "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": "[[concat('Bearer ',parameters('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 + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "contentProductId": "[concat(take(variables('_solutionId'), 50),'-','rdc','-', uniqueString(concat(variables('_solutionId'),'-','ResourcesDataConnector','-',variables('_dataConnectorContentIdConnections1'),'-', variables('dataConnectorCCPVersion'))))]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "version": "[variables('dataConnectorCCPVersion')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('dataConnectorTemplateNameConnectorDefinition2'), variables('dataConnectorCCPVersion'))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition2')]", + "displayName": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "contentKind": "DataConnector", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('dataConnectorCCPVersion')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentIdConnectorDefinition2'))]", + "apiVersion": "2022-09-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectorDefinitions", + "location": "[parameters('workspace-location')]", + "kind": "Customizable", + "properties": { + "connectorUiConfig": { + "id": "MiroContentLogsDataConnector", + "title": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "publisher": "Miro", + "descriptionMarkdown": "The [Miro Content Logs](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview) data connector enables you to ingest content activity logs from Miro into Microsoft Sentinel. Part of Miro's Enterprise Guard eDiscovery capabilities, this connector provides content-level visibility for compliance, legal hold, and advanced threat detection.\n\n**Key features:**\n- Track all content item changes.\n- Monitor content modifications by user and timestamp.\n- Support compliance and eDiscovery requirements.\n- Detect data exfiltration and insider threats.\n- Meet regulatory and legal hold obligations.\n\n**Requirements:**\n- **Miro Plan**: [Enterprise Plan](https://miro.com/pricing/) + **Enterprise Guard** add-on.\n- **OAuth scope**: `contentlogs:export`.\n- **Role**: Company Admin in your Miro organization.\n- **Organization ID**: Your Miro organization identifier.\n\n💡 **Not on Enterprise Plan yet?** Upgrade to [Miro Enterprise](https://miro.com/enterprise/) to unlock advanced security and compliance features for your team's collaboration activities in Microsoft Sentinel.\n\n💡 **Need Content Logs?** Content activity logging is part of [Miro Enterprise Guard](https://miro.com/enterprise-guard/), which provides advanced security, compliance, and eDiscovery features. Contact your Miro account manager to add Enterprise Guard to your Enterprise Plan and unlock content-level monitoring in Microsoft Sentinel.\n\n**Note:** If you only have the base Enterprise Plan (without Enterprise Guard), please use the **Miro Audit Logs** connector instead for organization-level event monitoring.\n\nFor detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).", + "graphQueriesTableName": "MiroContentLogs_CL", + "graphQueries": [ + { + "metricName": "Miro Content Logs", + "legend": "MiroContentLogs_CL", + "baseQuery": "MiroContentLogs_CL" + } + ], + "sampleQueries": [ + { + "description": "Recent content changes", + "query": "MiroContentLogs_CL\n| sort by TimeGenerated desc\n| take 10" + }, + { + "description": "Activity by action type", + "query": "MiroContentLogs_CL\n| summarize count() by actionType\n| render piechart" + }, + { + "description": "Most active users", + "query": "MiroContentLogs_CL\n| summarize events = count() by actor_name\n| top 10 by events desc" + } + ], + "dataTypes": [ + { + "name": "MiroContentLogs_CL", + "lastDataReceivedQuery": "MiroContentLogs_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 with Enterprise Guard", + "description": "Miro Enterprise Plan with Enterprise Guard add-on is required. Content logs are part of Miro's eDiscovery features and are not available on base Enterprise Plan or lower tiers." + }, + { + "name": "Miro OAuth Application", + "description": "Miro OAuth application with contentlogs:export scope and Company Admin role is required." + }, + { + "name": "Miro Organization ID", + "description": "Your Miro organization ID is required to access content logs." + } + ] + }, + "instructionSteps": [ + { + "description": "**Step 1: Verify your Miro plan and Enterprise Guard**\n\n1. Ensure your organization has [Miro Enterprise Plan](https://miro.com/pricing/) with **Enterprise Guard** add-on.\n2. Content logs are part of Miro's eDiscovery (Enterprise Guard) features.\n3. If you don't have Enterprise Guard yet, contact your [Miro account manager](https://miro.com/contact/sales/) to upgrade.\n4. Without Enterprise Guard, use the **Miro Audit Logs** connector for organization-level monitoring.\n5. 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 Content 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 **eDiscovery** toggle.\n5. Copy the **Access Token** value that appears.\n6. Get your **Organization ID** from the browser URL:\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n7. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n8. The token will work until you disable the toggle.\n9. 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: **`contentlogs:export`**.\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. Get your **Organization ID**:\n - Go to [Miro Company Settings](https://miro.com/app/settings/).\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n9. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n10. The token will work until you uninstall the app." + }, + { + "description": "**Step 3: Learn more**\n\nFor detailed information about Miro content logs and eDiscovery:\n- [Miro Content Logs overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview)\n- [Miro Enterprise Guard](https://miro.com/enterprise-guard/)\n- [Miro API reference](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch)\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 the required values below to complete the connection.", + "instructions": [ + { + "type": "Textbox", + "parameters": { + "label": "Organization ID", + "placeholder": "Enter your Miro Organization ID", + "type": "text", + "name": "organizationId" + } + }, + { + "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 content logs in Microsoft Sentinel." + } + ] + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnectorDefinition2')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectorDefinitions', variables('_dataConnectorContentIdConnectorDefinition2'))]", + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition2')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + }, + "dependencies": { + "criteria": [ + { + "version": "[variables('dataConnectorCCPVersion')]", + "contentId": "[variables('_dataConnectorContentIdConnections2')]", + "kind": "ResourcesDataConnector" + } + ] + } + } + }, + { + "name": "MiroContentLogsDCR", + "apiVersion": "2022-06-01", + "type": "Microsoft.Insights/dataCollectionRules", + "location": "[parameters('workspace-location')]", + "kind": "[variables('blanks')]", + "properties": { + "streamDeclarations": { + "Custom-MiroContentLogs_CL": { + "columns": [ + { + "name": "id", + "type": "string" + }, + { + "name": "contentId", + "type": "string" + }, + { + "name": "actionType", + "type": "string" + }, + { + "name": "actionTime", + "type": "string" + }, + { + "name": "actor", + "type": "dynamic" + }, + { + "name": "itemType", + "type": "string" + }, + { + "name": "itemId", + "type": "string" + }, + { + "name": "state", + "type": "dynamic" + }, + { + "name": "relationships", + "type": "dynamic" + } + ] + } + }, + "dataSources": "[variables('TemplateEmptyObject')]", + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[variables('workspaceResourceId')]", + "name": "clv2ws1" + } + ] + }, + "dataFlows": [ + { + "streams": [ + "Custom-MiroContentLogs_CL" + ], + "destinations": [ + "clv2ws1" + ], + "transformKql": "source\n| extend TimeGenerated = todatetime(actionTime)\n| extend actionTime = todatetime(actionTime)\n| extend actor_id = iff(isnull(actor), \"\", tostring(actor.id))\n| extend actor_email = iff(isnull(actor), \"\", tostring(actor.email))\n| extend actor_name = iff(isnull(actor), \"\", tostring(actor.name))\n| project TimeGenerated, id, actionTime, actionType, actor_id, actor_email, actor_name, contentId, itemId, itemType, relationships, state", + "outputStream": "Custom-MiroContentLogs_CL" + } + ], + "dataCollectionEndpointId": "[variables('dataCollectionEndpointId2')]" + } + }, + { + "name": "MiroContentLogs_CL", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/tables", + "location": "[parameters('workspace-location')]", + "kind": null, + "properties": { + "schema": { + "name": "MiroContentLogs_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 content log event" + }, + { + "name": "actionTime", + "type": "datetime", + "description": "Timestamp when the action was performed" + }, + { + "name": "actionType", + "type": "string", + "description": "Type of action performed (create, update, delete, etc.)" + }, + { + "name": "actor_id", + "type": "string", + "description": "Unique identifier of the user who performed the action" + }, + { + "name": "actor_email", + "type": "string", + "description": "Email address of the user who performed the action" + }, + { + "name": "actor_name", + "type": "string", + "description": "Name of the user who performed the action" + }, + { + "name": "contentId", + "type": "string", + "description": "Unique identifier of the content affected" + }, + { + "name": "itemId", + "type": "string", + "description": "Unique identifier of the item affected" + }, + { + "name": "itemType", + "type": "string", + "description": "Type of the content item" + }, + { + "name": "relationships", + "type": "dynamic", + "description": "Relationships of the content item in JSON format" + }, + { + "name": "state", + "type": "dynamic", + "description": "State information of the content item in JSON format" + } + ] + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "contentProductId": "[concat(take(variables('_solutionId'), 50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentIdConnectorDefinition2'),'-', variables('dataConnectorCCPVersion'))))]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "version": "[variables('dataConnectorCCPVersion')]" + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentIdConnectorDefinition2'))]", + "apiVersion": "2022-09-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectorDefinitions", + "location": "[parameters('workspace-location')]", + "kind": "Customizable", + "properties": { + "connectorUiConfig": { + "id": "MiroContentLogsDataConnector", + "title": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "publisher": "Miro", + "descriptionMarkdown": "The [Miro Content Logs](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview) data connector enables you to ingest content activity logs from Miro into Microsoft Sentinel. Part of Miro's Enterprise Guard eDiscovery capabilities, this connector provides content-level visibility for compliance, legal hold, and advanced threat detection.\n\n**Key features:**\n- Track all content item changes.\n- Monitor content modifications by user and timestamp.\n- Support compliance and eDiscovery requirements.\n- Detect data exfiltration and insider threats.\n- Meet regulatory and legal hold obligations.\n\n**Requirements:**\n- **Miro Plan**: [Enterprise Plan](https://miro.com/pricing/) + **Enterprise Guard** add-on.\n- **OAuth scope**: `contentlogs:export`.\n- **Role**: Company Admin in your Miro organization.\n- **Organization ID**: Your Miro organization identifier.\n\n💡 **Not on Enterprise Plan yet?** Upgrade to [Miro Enterprise](https://miro.com/enterprise/) to unlock advanced security and compliance features for your team's collaboration activities in Microsoft Sentinel.\n\n💡 **Need Content Logs?** Content activity logging is part of [Miro Enterprise Guard](https://miro.com/enterprise-guard/), which provides advanced security, compliance, and eDiscovery features. Contact your Miro account manager to add Enterprise Guard to your Enterprise Plan and unlock content-level monitoring in Microsoft Sentinel.\n\n**Note:** If you only have the base Enterprise Plan (without Enterprise Guard), please use the **Miro Audit Logs** connector instead for organization-level event monitoring.\n\nFor detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).", + "graphQueriesTableName": "MiroContentLogs_CL", + "graphQueries": [ + { + "metricName": "Miro Content Logs", + "legend": "MiroContentLogs_CL", + "baseQuery": "MiroContentLogs_CL" + } + ], + "sampleQueries": [ + { + "description": "Recent content changes", + "query": "MiroContentLogs_CL\n| sort by TimeGenerated desc\n| take 10" + }, + { + "description": "Activity by action type", + "query": "MiroContentLogs_CL\n| summarize count() by actionType\n| render piechart" + }, + { + "description": "Most active users", + "query": "MiroContentLogs_CL\n| summarize events = count() by actor_name\n| top 10 by events desc" + } + ], + "dataTypes": [ + { + "name": "MiroContentLogs_CL", + "lastDataReceivedQuery": "MiroContentLogs_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 with Enterprise Guard", + "description": "Miro Enterprise Plan with Enterprise Guard add-on is required. Content logs are part of Miro's eDiscovery features and are not available on base Enterprise Plan or lower tiers." + }, + { + "name": "Miro OAuth Application", + "description": "Miro OAuth application with contentlogs:export scope and Company Admin role is required." + }, + { + "name": "Miro Organization ID", + "description": "Your Miro organization ID is required to access content logs." + } + ] + }, + "instructionSteps": [ + { + "description": "**Step 1: Verify your Miro plan and Enterprise Guard**\n\n1. Ensure your organization has [Miro Enterprise Plan](https://miro.com/pricing/) with **Enterprise Guard** add-on.\n2. Content logs are part of Miro's eDiscovery (Enterprise Guard) features.\n3. If you don't have Enterprise Guard yet, contact your [Miro account manager](https://miro.com/contact/sales/) to upgrade.\n4. Without Enterprise Guard, use the **Miro Audit Logs** connector for organization-level monitoring.\n5. 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 Content 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 **eDiscovery** toggle.\n5. Copy the **Access Token** value that appears.\n6. Get your **Organization ID** from the browser URL:\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n7. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n8. The token will work until you disable the toggle.\n9. 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: **`contentlogs:export`**.\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. Get your **Organization ID**:\n - Go to [Miro Company Settings](https://miro.com/app/settings/).\n - Look at the browser URL to find your Organization ID.\n - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`.\n - Copy your Organization ID from the URL (the numeric value).\n9. **Important:** Store both the token and Organization ID securely—they provide full access to content logs.\n10. The token will work until you uninstall the app." + }, + { + "description": "**Step 3: Learn more**\n\nFor detailed information about Miro content logs and eDiscovery:\n- [Miro Content Logs overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview)\n- [Miro Enterprise Guard](https://miro.com/enterprise-guard/)\n- [Miro API reference](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch)\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 the required values below to complete the connection.", + "instructions": [ + { + "type": "Textbox", + "parameters": { + "label": "Organization ID", + "placeholder": "Enter your Miro Organization ID", + "type": "text", + "name": "organizationId" + } + }, + { + "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 content logs in Microsoft Sentinel." + } + ] + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnectorDefinition2')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectorDefinitions', variables('_dataConnectorContentIdConnectorDefinition2'))]", + "contentId": "[variables('_dataConnectorContentIdConnectorDefinition2')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + }, + "dependencies": { + "criteria": [ + { + "version": "[variables('dataConnectorCCPVersion')]", + "contentId": "[variables('_dataConnectorContentIdConnections2')]", + "kind": "ResourcesDataConnector" + } + ] + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('dataConnectorTemplateNameConnections2'), variables('dataConnectorCCPVersion'))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "contentId": "[variables('_dataConnectorContentIdConnections2')]", + "displayName": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "contentKind": "ResourcesDataConnector", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('dataConnectorCCPVersion')]", + "parameters": { + "guidValue": { + "defaultValue": "[[newGuid()]", + "type": "securestring" + }, + "innerWorkspace": { + "defaultValue": "[parameters('workspace')]", + "type": "securestring" + }, + "connectorDefinitionName": { + "defaultValue": "Miro Content Logs (Enterprise Plan + Enterprise Guard)", + "type": "securestring", + "minLength": 1 + }, + "workspace": { + "defaultValue": "[parameters('workspace')]", + "type": "securestring" + }, + "dcrConfig": { + "defaultValue": { + "dataCollectionEndpoint": "data collection Endpoint", + "dataCollectionRuleImmutableId": "data collection rule immutableId" + }, + "type": "object" + }, + "organizationId": { + "defaultValue": "organizationId", + "type": "securestring", + "minLength": 1 + }, + "AccessToken": { + "defaultValue": "AccessToken", + "type": "securestring", + "minLength": 1 + } + }, + "variables": { + "_dataConnectorContentIdConnections2": "[variables('_dataConnectorContentIdConnections2')]" + }, + "resources": [ + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', variables('_dataConnectorContentIdConnections2')))]", + "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentIdConnections2'))]", + "contentId": "[variables('_dataConnectorContentIdConnections2')]", + "kind": "ResourcesDataConnector", + "version": "[variables('dataConnectorCCPVersion')]", + "source": { + "sourceId": "[variables('_solutionId')]", + "name": "[variables('_solutionName')]", + "kind": "Solution" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + } + } + }, + { + "name": "[[concat(parameters('innerWorkspace'),'/Microsoft.SecurityInsights/', 'MiroContentLogsPoller', parameters('guidValue'))]", + "apiVersion": "2023-02-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "location": "[parameters('workspace-location')]", + "kind": "RestApiPoller", + "properties": { + "connectorDefinitionName": "MiroContentLogsDataConnector", + "dcrConfig": { + "dataCollectionEndpoint": "[[parameters('dcrConfig').dataCollectionEndpoint]", + "dataCollectionRuleImmutableId": "[[parameters('dcrConfig').dataCollectionRuleImmutableId]", + "streamName": "Custom-MiroContentLogs_CL" + }, + "dataType": "Miro Content Logs", + "addOnAttributes": { + "OrganizationId": "[[parameters('organizationId')]" + }, + "response": { + "eventsJsonPaths": [ + "$.data" + ], + "format": "json" + }, + "paging": { + "pagingType": "NextPageToken", + "nextPageTokenJsonPath": "$.cursor", + "nextPageParaName": "cursor", + "pageSize": 100 + }, + "auth": { + "type": "APIKey", + "ApiKeyName": "Authorization", + "APIKey": "[[concat('Bearer ',parameters('AccessToken'))]", + "IsAPIKeyInPostPayload": false + }, + "request": { + "apiEndpoint": "[[concat('https://api.miro.com/v2/orgs/',parameters('organizationId'),'/content-logs/items')]", + "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-MiroContentLogsDataConnector" + }, + "StartTimeAttributeName": "from", + "EndTimeAttributeName": "to", + "queryParameters": { + "from": "{_QueryWindowStartTime}", + "to": "{_QueryWindowEndTime}", + "sorting": "asc", + "limit": "100" + } + }, + "isActive": true + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "contentProductId": "[concat(take(variables('_solutionId'), 50),'-','rdc','-', uniqueString(concat(variables('_solutionId'),'-','ResourcesDataConnector','-',variables('_dataConnectorContentIdConnections2'),'-', variables('dataConnectorCCPVersion'))))]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "version": "[variables('dataConnectorCCPVersion')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", + "apiVersion": "2023-04-01-preview", + "location": "[parameters('workspace-location')]", + "properties": { + "version": "3.0.0", + "kind": "Solution", + "contentSchemaVersion": "3.0.0", + "displayName": "Miro", + "publisherDisplayName": "Miro", + "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Miro solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from Miro REST APIs into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the documentation.

\n

Underlying Microsoft technology used:

\n

This solution is dependent on the following technology and this dependency may be in Preview state or might result in additional ingestion or operational costs:

\n

• Codeless Connector Framework (CCF)

\n

Data Connectors: 2

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "contentKind": "Solution", + "contentProductId": "[variables('_solutioncontentProductId')]", + "id": "[variables('_solutioncontentProductId')]", + "icon": "", + "contentId": "[variables('_solutionId')]", + "parentId": "[variables('_solutionId')]", + "source": { + "kind": "Solution", + "name": "Miro", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Miro", + "email": "[variables('_email')]" + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "kind": "DataConnector", + "contentId": "[variables('_dataConnectorContentIdConnections1')]", + "version": "[variables('dataConnectorCCPVersion')]" + }, + { + "kind": "DataConnector", + "contentId": "[variables('_dataConnectorContentIdConnections2')]", + "version": "[variables('dataConnectorCCPVersion')]" + } + ] + }, + "providers": [ + "Miro" + ], + "categories": { + "domains": [ + "Security - Insider Threat", + "Security - Information Protection", + "Security - Threat Protection", + "Security - Cloud Security", + "Compliance", + "User Behavior (UEBA)", + "Application" + ] + } + }, + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('_solutionId'))]" + } + ], + "outputs": {} +} diff --git a/Solutions/Miro/Package/testParameters.json b/Solutions/Miro/Package/testParameters.json new file mode 100644 index 00000000000..554801e41b7 --- /dev/null +++ b/Solutions/Miro/Package/testParameters.json @@ -0,0 +1,38 @@ +{ + "location": { + "type": "string", + "minLength": 1, + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Not used, but needed to pass arm-ttk test `Location-Should-Not-Be-Hardcoded`. We instead use the `workspace-location` which is derived from the LA workspace" + } + }, + "workspace-location": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "[concat('Region to deploy solution resources -- separate from location selection',parameters('location'))]" + } + }, + "workspace": { + "defaultValue": "", + "type": "string", + "metadata": { + "description": "Workspace name for Log Analytics where Microsoft Sentinel is setup" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "resource group name where Microsoft Sentinel is setup" + } + }, + "subscription": { + "type": "string", + "defaultValue": "[last(split(subscription().id, '/'))]", + "metadata": { + "description": "subscription id where Microsoft Sentinel is setup" + } + } +} diff --git a/Solutions/Miro/README.md b/Solutions/Miro/README.md new file mode 100644 index 00000000000..3ff41bf2e47 --- /dev/null +++ b/Solutions/Miro/README.md @@ -0,0 +1,266 @@ +# Miro Solution for Microsoft Sentinel + +Miro
+ +## Overview + +The [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362). + +**Underlying Microsoft technology used:** + +This solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs: + +• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector) + +## Data Connectors + +This solution includes two data connectors: + +1. **Miro Audit Logs (Enterprise Plan)**: Organization-wide audit events including user authentication, content access, team changes, and administrative actions. [API Documentation](https://developers.miro.com/reference/enterprise-get-audit-logs) | [Audit Logs Overview](https://developers.miro.com/reference/audit-logs) +2. **Miro Content Logs (Enterprise Plan + Enterprise Guard)**: Content activity tracking including item creation, updates, and deletions for compliance and eDiscovery. [API Documentation](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch) | [Content Logs Overview](https://developers.miro.com/reference/board-content-logs) + +## Prerequisites + +### General Requirements +- Active Microsoft Sentinel workspace +- Company Admin role in Miro organization +- Miro OAuth Access Token (non-expiring) + +### Connector-Specific Requirements + +**For Audit Logs Connector:** +- Miro Enterprise Plan +- OAuth scope: `auditlogs:read` +- Access Token + +**For Content Logs Connector:** +- Miro Enterprise Plan + Enterprise Guard add-on +- OAuth scope: `contentlogs:export` +- Access Token +- Miro Organization ID + +## Installation + +There are two ways to set up the Miro connectors: + +- **Method 1 (Recommended):** Use Enterprise Integrations - Simplest setup with automatic token generation +- **Method 2 (Alternative):** Create Custom OAuth Application - More control over OAuth app configuration + +**Note:** When using Method 1, the integration is automatically tied to the team with the largest number of users in your organization. When using Method 2, you can choose which team to install the app to. However, **the team selection does not affect which logs are collected** - both methods provide organization-wide log access. All integration-relevant events from all teams are included in your logs. + +--- + +### Method 1: Using Enterprise Integrations (Recommended) + +This is the simplest method for most users. It automatically creates an OAuth application and generates an access token for you through Miro's Enterprise Integrations settings. + +#### For Audit Logs Connector: + +1. Open [Miro Company Settings](https://miro.com/app/settings/) +2. Expand the **Apps and integrations** section +3. Click **Enterprise integrations** +4. Enable the **SIEM** toggle +5. Copy the **Access Token** value that appears +6. Store the token securely + +#### For Content Logs Connector: + +1. Open [Miro Company Settings](https://miro.com/app/settings/) +2. Expand the **Apps and integrations** section +3. Click **Enterprise integrations** +4. Enable the **eDiscovery** toggle +5. Copy the **Access Token** value that appears +6. Get your **Organization ID** from the browser URL: + - Look at the browser URL to find your Organization ID + - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/` + - Copy your Organization ID from the URL (the numeric value) +7. Store both the token and Organization ID securely + +--- + +### Method 2: Using Custom OAuth Application (Alternative) + +This method gives you more control over the OAuth application configuration. Use this if you need to customize scopes, manage multiple integrations, or prefer manual OAuth app management. + +#### Step 1: Create Miro OAuth Application + +1. Log in to your Miro account +2. Go to [Miro App Settings](https://miro.com/app/settings/user-profile/apps) +3. Click **Create new app** +4. Select **Non-expiring access token** option during app creation ([Learn more about OAuth tokens](https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens)) +5. Enable required OAuth scopes: + - `auditlogs:read` for Audit Logs connector + - `contentlogs:export` for Content Logs connector (requires Enterprise Guard) +6. Click **Install app and get OAuth token** +7. Copy the **Access Token** and store it securely + +For detailed OAuth setup instructions, see [Getting Started with OAuth](https://developers.miro.com/docs/getting-started-with-oauth). + +#### Step 2: Get Organization ID (for Content Logs only) + +1. Go to [Miro Company Settings](https://miro.com/app/settings/) +2. Look at the browser URL to find your Organization ID + - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/` + - Copy your Organization ID from the URL (the numeric value) + +--- + +### Deploy Solution in Microsoft Sentinel + +1. In Microsoft Sentinel, navigate to **Content Hub** +2. Search for **"Miro"** and click the solution +3. Click **Install** and follow the deployment wizard +4. Select your Log Analytics workspace +5. Complete the installation + +### Configure Data Connectors + +#### Miro Audit Logs Connector + +1. In Microsoft Sentinel, go to **Data connectors** +2. Find **Miro Audit Logs (Enterprise Plan)** and click **Open connector page** +3. Click **Connect** +4. Enter your **Access Token** +5. Click **Connect** to activate the connector + +#### Miro Content Logs Connector + +1. In Microsoft Sentinel, go to **Data connectors** +2. Find **Miro Content Logs (Enterprise Plan + Enterprise Guard)** and click **Open connector page** +3. Click **Connect** +4. Enter your **Organization ID** +5. Enter your **Access Token** +6. Click **Connect** to activate the connector + +Data ingestion begins within 5-10 minutes after connector activation. + +## Data Tables + +### MiroAuditLogs_CL + +Organization-level audit events including: +- User authentication and access +- Content operations +- Team and organization changes +- User profile modifications +- Administrative actions + +Key columns: +- `TimeGenerated`: Event timestamp +- `event`: Event name identifying the specific action or activity +- `logType`: Type of log entry +- `category`: Event category grouping related events +- `createdBy_email`: User who triggered the event +- `context_ip`: IP address of the event +- `details`: Additional event-specific information (JSON) + +### MiroContentLogs_CL + +Content-level activity logs including: +- Item-level operations with user attribution and timestamps +- State transitions and modifications +- Activity tracking for compliance and eDiscovery + +Key columns: +- `TimeGenerated`: Event timestamp +- `actionType`: Type of action performed on the content +- `actor_email`: User who performed the action +- `itemType`: Type of content item affected +- `contentId`: Unique identifier of the content +- `state`: Item state information (JSON) + +## Sample Queries + +### View Recent Audit Events + +```kusto +MiroAuditLogs_CL +| sort by TimeGenerated desc +| project TimeGenerated, event, category, createdBy_email, context_ip +| take 20 +``` + +### Activity by User and Event Type + +```kusto +MiroAuditLogs_CL +| summarize EventCount = count() by createdBy_email, event, category +| order by EventCount desc +``` + +### Content Changes by User + +```kusto +MiroContentLogs_CL +| where TimeGenerated > ago(7d) +| summarize Changes = count() by actor_email, actionType +| order by Changes desc +``` + +### Event Trends Over Time + +```kusto +MiroAuditLogs_CL +| summarize count() by event, bin(TimeGenerated, 1h) +| render timechart +``` + +### Most Active Users (Content Changes) + +```kusto +MiroContentLogs_CL +| where TimeGenerated > ago(30d) +| summarize TotalActions = count() by actor_email +| top 10 by TotalActions desc +``` + +## Troubleshooting + +### No Data Appearing + +- Verify the access token is valid and has correct scopes +- For Content Logs, confirm your organization has Enterprise Guard add-on +- Confirm Organization ID is correct (for Content Logs) +- Wait 5-10 minutes for initial data ingestion +- Check connector status in the Data connectors page + +### Authentication Errors + +**If using Method 1 (Enterprise Integrations toggle):** +- Go to [Company Settings](https://miro.com/app/settings/) > expand **Apps and integrations** > click **Enterprise integrations** +- Verify the toggle (SIEM for Audit Logs, eDiscovery for Content Logs) is still enabled +- If another admin disabled the toggle, the token will be invalidated +- Re-enable the toggle to generate a new token and update the connector configuration +- Verify you have Company Admin role in Miro + +**If using Method 2 (Custom OAuth app):** +- Verify the token hasn't been revoked in [Miro App Settings](https://miro.com/app/settings/user-profile/apps) +- Ensure the OAuth application has the required scopes enabled +- Regenerate the token if needed and update in the connector configuration +- Verify you have Company Admin role in Miro + +### Content Logs Not Working + +- Verify your Miro plan includes **Enterprise Guard** add-on (not available on base Enterprise Plan) +- Confirm the OAuth scope `contentlogs:export` is enabled +- Double-check the Organization ID is correct +- Contact your Miro account manager if you need to upgrade to Enterprise Guard + +## Support + +### Miro Resources +- **Miro Help Center**: [https://help.miro.com](https://help.miro.com) +- **Miro Audit Logs**: [https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs](https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs) +- **Miro Content Logs**: [https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview) +- **Miro Sentinel Integration Guide**: [https://help.miro.com/hc/en-us/articles/31325908249362](https://help.miro.com/hc/en-us/articles/31325908249362) + +### Miro Developer Documentation +- **Getting Started with Enterprise API**: [https://developers.miro.com/docs/getting-started-with-enterprise-api](https://developers.miro.com/docs/getting-started-with-enterprise-api) +- **Getting Started with OAuth**: [https://developers.miro.com/docs/getting-started-with-oauth](https://developers.miro.com/docs/getting-started-with-oauth) +- **OAuth Token Authorization**: [https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens](https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens) +- **Audit Logs API**: [https://developers.miro.com/reference/enterprise-get-audit-logs](https://developers.miro.com/reference/enterprise-get-audit-logs) +- **Content Logs API**: [https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch) +- **API Reference**: [https://developers.miro.com/reference](https://developers.miro.com/reference) + +### Microsoft Sentinel +- **Microsoft Sentinel Documentation**: [https://docs.microsoft.com/azure/sentinel/](https://docs.microsoft.com/azure/sentinel/) diff --git a/Solutions/Miro/ReleaseNotes.md b/Solutions/Miro/ReleaseNotes.md new file mode 100644 index 00000000000..85cd636d869 --- /dev/null +++ b/Solutions/Miro/ReleaseNotes.md @@ -0,0 +1,3 @@ +| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | +|-------------|--------------------------------|-------------------------------------------------------------------------------------------------| +| 3.0.0 | 05-12-2025 | Initial release of the Miro solution with two **CCF connectors** (Audit Logs and Content Logs). | diff --git a/Solutions/Miro/SolutionMetadata.json b/Solutions/Miro/SolutionMetadata.json new file mode 100644 index 00000000000..c595eb9085a --- /dev/null +++ b/Solutions/Miro/SolutionMetadata.json @@ -0,0 +1,22 @@ +{ + "publisherId": "miro", + "offerId": "azure-sentinel-solution-miro", + "providers": ["Miro"], + "categories": { + "domains": [ + "Security - Insider Threat", + "Security - Information Protection", + "Security - Threat Protection", + "Security - Cloud Security", + "Compliance", + "User Behavior (UEBA)", + "Application" + ] + }, + "support": { + "name": "Miro", + "email": "enterprise_integrations@miro.com", + "tier": "Partner", + "link": "https://help.miro.com" + } +} From 86f6e59c837d8e73742cda24745dcc88ed98c7a1 Mon Sep 17 00:00:00 2001 From: Ilia Sretenskii Date: Fri, 5 Dec 2025 16:30:09 +0400 Subject: [PATCH 2/5] Update Miro solution README with editorial improvements Improve README formatting and consistency: - Standardize section header capitalization - Improve punctuation and grammar consistency - Update OAuth documentation link to non-expiring tokens - Change "Method" to "Option" for better clarity - Remove redundant CCF dependency section --- Solutions/Miro/README.md | 304 ++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 149 deletions(-) diff --git a/Solutions/Miro/README.md b/Solutions/Miro/README.md index 3ff41bf2e47..de288270b20 100644 --- a/Solutions/Miro/README.md +++ b/Solutions/Miro/README.md @@ -1,4 +1,4 @@ -# Miro Solution for Microsoft Sentinel +# Miro solution for Microsoft Sentinel Miro
@@ -6,172 +6,173 @@ The [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362). -**Underlying Microsoft technology used:** +## Data connectors -This solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs: +This solution includes two data connectors: -• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector) +1. **Miro Audit Logs (Enterprise Plan)**: Organization-wide audit events including user authentication, content access, team changes, and administrative actions. [API documentation](https://developers.miro.com/reference/enterprise-get-audit-logs) | [Audit logs overview](https://developers.miro.com/reference/audit-logs). +2. **Miro Content Logs (Enterprise Plan + Enterprise Guard)**: Content activity tracking including item creation, updates, and deletions for compliance and eDiscovery. [API documentation](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch) | [Content logs overview](https://developers.miro.com/reference/board-content-logs). -## Data Connectors +## Prerequisites -This solution includes two data connectors: +### General requirements -1. **Miro Audit Logs (Enterprise Plan)**: Organization-wide audit events including user authentication, content access, team changes, and administrative actions. [API Documentation](https://developers.miro.com/reference/enterprise-get-audit-logs) | [Audit Logs Overview](https://developers.miro.com/reference/audit-logs) -2. **Miro Content Logs (Enterprise Plan + Enterprise Guard)**: Content activity tracking including item creation, updates, and deletions for compliance and eDiscovery. [API Documentation](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch) | [Content Logs Overview](https://developers.miro.com/reference/board-content-logs) +- Active Microsoft Sentinel workspace. +- Company Admin role in your Miro organization. +- Miro OAuth access token (non-expiring). -## Prerequisites +### Connector-specific requirements -### General Requirements -- Active Microsoft Sentinel workspace -- Company Admin role in Miro organization -- Miro OAuth Access Token (non-expiring) +**For audit logs connector:** -### Connector-Specific Requirements +- Miro Enterprise Plan. +- OAuth scope: `auditlogs:read`. +- Access token. -**For Audit Logs Connector:** -- Miro Enterprise Plan -- OAuth scope: `auditlogs:read` -- Access Token +**For content logs connector:** -**For Content Logs Connector:** -- Miro Enterprise Plan + Enterprise Guard add-on -- OAuth scope: `contentlogs:export` -- Access Token -- Miro Organization ID +- Miro Enterprise Plan + Enterprise Guard add-on. +- OAuth scope: `contentlogs:export`. +- Access token. +- Miro organization ID. ## Installation -There are two ways to set up the Miro connectors: +There are two ways to set up the Miro connectors. -- **Method 1 (Recommended):** Use Enterprise Integrations - Simplest setup with automatic token generation -- **Method 2 (Alternative):** Create Custom OAuth Application - More control over OAuth app configuration +- **Option 1 (recommended):** Use enterprise integrations. Simplest setup with automatic token generation. +- **Option 2 (alternative):** Create custom OAuth application. More control over OAuth app configuration. -**Note:** When using Method 1, the integration is automatically tied to the team with the largest number of users in your organization. When using Method 2, you can choose which team to install the app to. However, **the team selection does not affect which logs are collected** - both methods provide organization-wide log access. All integration-relevant events from all teams are included in your logs. +**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. --- -### Method 1: Using Enterprise Integrations (Recommended) +### Option 1: Use enterprise integrations (recommended) -This is the simplest method for most users. It automatically creates an OAuth application and generates an access token for you through Miro's Enterprise Integrations settings. +This is the simplest option for most users. It automatically creates an OAuth application and generates an access token for you through Miro's enterprise integrations settings. -#### For Audit Logs Connector: +#### For audit logs connector -1. Open [Miro Company Settings](https://miro.com/app/settings/) -2. Expand the **Apps and integrations** section -3. Click **Enterprise integrations** -4. Enable the **SIEM** toggle -5. Copy the **Access Token** value that appears -6. Store the token securely +1. Open [Miro company settings](https://miro.com/app/settings/). +2. Expand the **Apps and integrations** section. +3. Click **Enterprise integrations**. +4. Enable the **SIEM** toggle. +5. Copy the **Access Token** value that appears. +6. Store the token securely. -#### For Content Logs Connector: +#### For content logs connector -1. Open [Miro Company Settings](https://miro.com/app/settings/) -2. Expand the **Apps and integrations** section -3. Click **Enterprise integrations** -4. Enable the **eDiscovery** toggle -5. Copy the **Access Token** value that appears +1. Open [Miro company settings](https://miro.com/app/settings/). +2. Expand the **Apps and integrations** section. +3. Click **Enterprise integrations**. +4. Enable the **eDiscovery** toggle. +5. Copy the **Access Token** value that appears. 6. Get your **Organization ID** from the browser URL: - - Look at the browser URL to find your Organization ID - - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/` - - Copy your Organization ID from the URL (the numeric value) -7. Store both the token and Organization ID securely + - Look at the browser URL to find your organization ID. + - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`. + - Copy your organization ID from the URL (the numeric value). +7. Store both the token and organization ID securely. --- -### Method 2: Using Custom OAuth Application (Alternative) +### Option 2: Use custom OAuth application (alternative) -This method gives you more control over the OAuth application configuration. Use this if you need to customize scopes, manage multiple integrations, or prefer manual OAuth app management. +This option gives you more control over the OAuth application configuration. Use this if you need to customize scopes, manage multiple integrations, or prefer manual OAuth app management. -#### Step 1: Create Miro OAuth Application +#### Step 1: Create Miro OAuth application -1. Log in to your Miro account -2. Go to [Miro App Settings](https://miro.com/app/settings/user-profile/apps) -3. Click **Create new app** -4. Select **Non-expiring access token** option during app creation ([Learn more about OAuth tokens](https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens)) -5. Enable required OAuth scopes: - - `auditlogs:read` for Audit Logs connector - - `contentlogs:export` for Content Logs connector (requires Enterprise Guard) -6. Click **Install app and get OAuth token** -7. Copy the **Access Token** and store it securely +1. Log in to your Miro account. +2. Go to [Miro app settings](https://miro.com/app/settings/user-profile/apps). +3. Click **Create new app**. +4. Select the **Non-expiring access token** option during app creation ([learn more about OAuth tokens](https://developers.miro.com/reference/authorization-flow-for-non-expiring-access-tokens)). +5. Enable the required OAuth scopes: + - `auditlogs:read` for the audit logs connector. + - `contentlogs:export` for the content logs connector (requires Enterprise Guard). +6. Click **Install app and get OAuth token**. +7. Copy the **Access Token** and store it securely. -For detailed OAuth setup instructions, see [Getting Started with OAuth](https://developers.miro.com/docs/getting-started-with-oauth). +For detailed OAuth setup instructions, see [Getting started with OAuth](https://developers.miro.com/docs/getting-started-with-oauth). -#### Step 2: Get Organization ID (for Content Logs only) +#### Step 2: Get organization ID (for content logs only) -1. Go to [Miro Company Settings](https://miro.com/app/settings/) -2. Look at the browser URL to find your Organization ID - - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/` - - Copy your Organization ID from the URL (the numeric value) +1. Go to [Miro company settings](https://miro.com/app/settings/). +2. Look at the browser URL to find your organization ID. + - The URL format is: `https://miro.com/app/settings/company/{ORGANIZATION_ID}/`. + - Copy your organization ID from the URL (the numeric value). --- -### Deploy Solution in Microsoft Sentinel +### Deploy solution in Microsoft Sentinel -1. In Microsoft Sentinel, navigate to **Content Hub** -2. Search for **"Miro"** and click the solution -3. Click **Install** and follow the deployment wizard -4. Select your Log Analytics workspace -5. Complete the installation +1. In Microsoft Sentinel, navigate to **Content Hub**. +2. Search for **"Miro"** and click the solution. +3. Click **Install** and follow the deployment wizard. +4. Select your Log Analytics workspace. +5. Complete the installation. -### Configure Data Connectors +### Configure data connectors -#### Miro Audit Logs Connector +#### Miro audit logs connector -1. In Microsoft Sentinel, go to **Data connectors** -2. Find **Miro Audit Logs (Enterprise Plan)** and click **Open connector page** -3. Click **Connect** -4. Enter your **Access Token** -5. Click **Connect** to activate the connector +1. In Microsoft Sentinel, go to **Data connectors**. +2. Find **Miro Audit Logs (Enterprise Plan)** and click **Open connector page**. +3. Click **Connect**. +4. Enter your **Access Token**. +5. Click **Connect** to activate the connector. -#### Miro Content Logs Connector +#### Miro content logs connector -1. In Microsoft Sentinel, go to **Data connectors** -2. Find **Miro Content Logs (Enterprise Plan + Enterprise Guard)** and click **Open connector page** -3. Click **Connect** -4. Enter your **Organization ID** -5. Enter your **Access Token** -6. Click **Connect** to activate the connector +1. In Microsoft Sentinel, go to **Data connectors**. +2. Find **Miro Content Logs (Enterprise Plan + Enterprise Guard)** and click **Open connector page**. +3. Click **Connect**. +4. Enter your **Organization ID**. +5. Enter your **Access Token**. +6. Click **Connect** to activate the connector. -Data ingestion begins within 5-10 minutes after connector activation. +Data ingestion begins within 5–10 minutes after connector activation. -## Data Tables +## Data tables ### MiroAuditLogs_CL Organization-level audit events including: -- User authentication and access -- Content operations -- Team and organization changes -- User profile modifications -- Administrative actions + +- User authentication and access. +- Content operations. +- Team and organization changes. +- User profile modifications. +- Administrative actions. Key columns: -- `TimeGenerated`: Event timestamp -- `event`: Event name identifying the specific action or activity -- `logType`: Type of log entry -- `category`: Event category grouping related events -- `createdBy_email`: User who triggered the event -- `context_ip`: IP address of the event -- `details`: Additional event-specific information (JSON) + +- `TimeGenerated`: Event timestamp. +- `event`: Event name identifying the specific action or activity. +- `logType`: Type of log entry. +- `category`: Event category grouping related events. +- `createdBy_email`: User who triggered the event. +- `context_ip`: IP address of the event. +- `details`: Additional event-specific information (JSON). ### MiroContentLogs_CL Content-level activity logs including: -- Item-level operations with user attribution and timestamps -- State transitions and modifications -- Activity tracking for compliance and eDiscovery + +- Item-level operations with user attribution and timestamps. +- State transitions and modifications. +- Activity tracking for compliance and eDiscovery. Key columns: -- `TimeGenerated`: Event timestamp -- `actionType`: Type of action performed on the content -- `actor_email`: User who performed the action -- `itemType`: Type of content item affected -- `contentId`: Unique identifier of the content -- `state`: Item state information (JSON) -## Sample Queries +- `TimeGenerated`: Event timestamp. +- `actionType`: Type of action performed on the content. +- `actor_email`: User who performed the action. +- `itemType`: Type of content item affected. +- `contentId`: Unique identifier of the content. +- `state`: Item state information (JSON). -### View Recent Audit Events +## Sample queries + +### View recent audit events ```kusto MiroAuditLogs_CL @@ -180,7 +181,7 @@ MiroAuditLogs_CL | take 20 ``` -### Activity by User and Event Type +### Activity by user and event type ```kusto MiroAuditLogs_CL @@ -188,7 +189,7 @@ MiroAuditLogs_CL | order by EventCount desc ``` -### Content Changes by User +### Content changes by user ```kusto MiroContentLogs_CL @@ -197,7 +198,7 @@ MiroContentLogs_CL | order by Changes desc ``` -### Event Trends Over Time +### Event trends over time ```kusto MiroAuditLogs_CL @@ -205,7 +206,7 @@ MiroAuditLogs_CL | render timechart ``` -### Most Active Users (Content Changes) +### Most active users (content changes) ```kusto MiroContentLogs_CL @@ -216,51 +217,56 @@ MiroContentLogs_CL ## Troubleshooting -### No Data Appearing +### No data appearing + +- Verify the access token is valid and has the correct scopes. +- For content logs, confirm your organization has the Enterprise Guard add-on. +- Confirm the organization ID is correct (for content logs). +- Wait 5–10 minutes for initial data ingestion. +- Check the connector status in the **Data connectors** page. + +### Authentication errors -- Verify the access token is valid and has correct scopes -- For Content Logs, confirm your organization has Enterprise Guard add-on -- Confirm Organization ID is correct (for Content Logs) -- Wait 5-10 minutes for initial data ingestion -- Check connector status in the Data connectors page +**If using Option 1 (enterprise integrations toggle):** -### Authentication Errors +- Go to [Miro company settings](https://miro.com/app/settings/), expand **Apps and integrations**, and click **Enterprise integrations**. +- Verify the toggle (SIEM for audit logs, eDiscovery for content logs) is still enabled. +- If another admin disabled the toggle, the token will be invalidated. +- Re-enable the toggle to generate a new token and update the connector configuration. +- Verify you have the Company Admin role in Miro. -**If using Method 1 (Enterprise Integrations toggle):** -- Go to [Company Settings](https://miro.com/app/settings/) > expand **Apps and integrations** > click **Enterprise integrations** -- Verify the toggle (SIEM for Audit Logs, eDiscovery for Content Logs) is still enabled -- If another admin disabled the toggle, the token will be invalidated -- Re-enable the toggle to generate a new token and update the connector configuration -- Verify you have Company Admin role in Miro +**If using Option 2 (custom OAuth app):** -**If using Method 2 (Custom OAuth app):** -- Verify the token hasn't been revoked in [Miro App Settings](https://miro.com/app/settings/user-profile/apps) -- Ensure the OAuth application has the required scopes enabled -- Regenerate the token if needed and update in the connector configuration -- Verify you have Company Admin role in Miro +- Verify the token has not been revoked in [Miro app settings](https://miro.com/app/settings/user-profile/apps). +- Ensure the OAuth application has the required scopes enabled. +- Regenerate the token if needed and update it in the connector configuration. +- Verify you have the Company Admin role in Miro. -### Content Logs Not Working +### Content logs not working -- Verify your Miro plan includes **Enterprise Guard** add-on (not available on base Enterprise Plan) -- Confirm the OAuth scope `contentlogs:export` is enabled -- Double-check the Organization ID is correct -- Contact your Miro account manager if you need to upgrade to Enterprise Guard +- Verify your Miro plan includes the **Enterprise Guard** add-on (not available on the base Enterprise Plan). +- Confirm the OAuth scope `contentlogs:export` is enabled. +- Double-check that the organization ID is correct. +- Contact your Miro account manager if you need to upgrade to Enterprise Guard. ## Support -### Miro Resources -- **Miro Help Center**: [https://help.miro.com](https://help.miro.com) -- **Miro Audit Logs**: [https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs](https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs) -- **Miro Content Logs**: [https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview) -- **Miro Sentinel Integration Guide**: [https://help.miro.com/hc/en-us/articles/31325908249362](https://help.miro.com/hc/en-us/articles/31325908249362) +### Miro resources -### Miro Developer Documentation -- **Getting Started with Enterprise API**: [https://developers.miro.com/docs/getting-started-with-enterprise-api](https://developers.miro.com/docs/getting-started-with-enterprise-api) -- **Getting Started with OAuth**: [https://developers.miro.com/docs/getting-started-with-oauth](https://developers.miro.com/docs/getting-started-with-oauth) -- **OAuth Token Authorization**: [https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens](https://developers.miro.com/reference/authorization-flow-for-expiring-access-tokens) -- **Audit Logs API**: [https://developers.miro.com/reference/enterprise-get-audit-logs](https://developers.miro.com/reference/enterprise-get-audit-logs) -- **Content Logs API**: [https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch) -- **API Reference**: [https://developers.miro.com/reference](https://developers.miro.com/reference) +- **Miro Help Center**: [https://help.miro.com](https://help.miro.com). +- **Miro Audit Logs**: [https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs](https://help.miro.com/hc/en-us/articles/360017571434-Audit-logs). +- **Miro Content Logs**: [https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview](https://help.miro.com/hc/en-us/articles/17774729839378-Content-Logs-overview). +- **Miro Sentinel integration guide**: [https://help.miro.com/hc/en-us/articles/31325908249362](https://help.miro.com/hc/en-us/articles/31325908249362). + +### Miro developer documentation + +- **Getting started with Enterprise API**: [https://developers.miro.com/docs/getting-started-with-enterprise-api](https://developers.miro.com/docs/getting-started-with-enterprise-api). +- **Getting started with OAuth**: [https://developers.miro.com/docs/getting-started-with-oauth](https://developers.miro.com/docs/getting-started-with-oauth). +- **OAuth token authorization**: [https://developers.miro.com/reference/authorization-flow-for-non-expiring-access-tokens](https://developers.miro.com/reference/authorization-flow-for-non-expiring-access-tokens). +- **Audit Logs API**: [https://developers.miro.com/reference/enterprise-get-audit-logs](https://developers.miro.com/reference/enterprise-get-audit-logs). +- **Content Logs API**: [https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch](https://developers.miro.com/reference/enterprise-board-content-item-logs-fetch). +- **API reference**: [https://developers.miro.com/reference](https://developers.miro.com/reference). ### Microsoft Sentinel -- **Microsoft Sentinel Documentation**: [https://docs.microsoft.com/azure/sentinel/](https://docs.microsoft.com/azure/sentinel/) + +- **Microsoft Sentinel documentation**: [https://docs.microsoft.com/azure/sentinel/](https://docs.microsoft.com/azure/sentinel/). From a28c57a229fb5b307ed300c2ec941a5aaab5b670 Mon Sep 17 00:00:00 2001 From: Ilia Sretenskii Date: Thu, 18 Dec 2025 11:49:42 +0400 Subject: [PATCH 3/5] Update Miro Publisher ID and rebuild solution package v3.0.0 - Update publisherId to realtimeboardincdbamiro1645117589045 - Update README with improved overview description - Rebuild package with V3 tool --- Solutions/Miro/Package/3.0.0.zip | Bin 12499 -> 12540 bytes Solutions/Miro/Package/mainTemplate.json | 3 ++- Solutions/Miro/README.md | 2 +- Solutions/Miro/SolutionMetadata.json | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Solutions/Miro/Package/3.0.0.zip b/Solutions/Miro/Package/3.0.0.zip index 0cdf3c2c4ba8c1cca08897fbd0ab76d068d57778..cc3ad968fcf29172b3347fae2d10993801ca398e 100644 GIT binary patch delta 9600 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 delta 9558 zcmV-cC8^r{Vbfs^P)h>@6aWAK2mn1=g|Q7R2Y)?UgL?yZE$R1bY(7Tb8l|#eeH7GwvzULUj=G5RU^&Lha@NQu`2PdEIW>lzZ6SOYLAt2 zAQGCvF^6CXQ1T?3s&fr*?fV3hz8JXkWA?nS9i1^`TqJA0Aafqj6PC_xpza=pldu*OQ*T8VWLvv45Z}1NQDA^oM+PgkwA>g2a6J@_>1A^!yiudSVd~7?X>bhST(IKspUykZ>wyy+gF0 z|LT(~oCM-W93-;WyO?m6#2$GTvn1Nt9cQojSsSS=gmfhC#WYIE>AhkCC7k#}bbpx$ z6cXYS9|?vc%sImGd?dsNBnTJimlx?PMrSjY1peq16Qjpu^gWJ!kNL#^WsJ~I1ksQS zf_)eji5Wq^+_3lqkFZBZ8IixBn;G?Hh;rnUm|hbfUBzrJo4+_hc?Xax{P&0aUnyUN zde!k<kwqo~+vC!s}1jyHJSdO2=QYDLM*qun^Sa=w?P@f?iTDW}ICK zbVfo!LlVG*aw3w*%tJwEU*S1fW!@^94>Y#b`fLm|g+UaXD>B8COMU3}{C@Ej^kw`MIjX4g2T_%a}xEhBSG19*w60ezqMc$W{i)0aQ? zbIyA2vt^X(g*4NZhnl^=pIdvFg!K7|504}Ta&sB+l+#hxVl+36tNQ8mEuUya=8N!6 zsy}JJOr1{ro&G$N^7wT`lz&Wca1wGloe4h4mlp32k!}I)jUY|kAJ73A2A9Y3bgbm z`r7A{;x?l{0|F-nTUu^iG1sz76tipUlbBC(dos?|+e~A5V56>I1~~j6y{vaJi304A zo&IHih}8en7GX9ePv?;ls=s2G?WCHwjSmFV;W{!Q(&n3m`j;fZ4JG1QBqx2l{m>Cg=d9hNAXeB zSY-d{ve@M6UD-`7GHf6qSqg-%^ zgi=${f+Y~4qTv)GcPyUbkp8BEcQ@202um8sH3T+Qgi4Y|L%|GTf-!o@LJH$2oWuxw zf?j`9n8zXF>3T`W8Uih_C=m8M!ub#hg6GJaVW4D)aOflK&uK`x042UAax@llAeV$Q z9C`$(kC!8Z(x}ja?C!C76j0gD!x6rufh1*o5nhCY!E>@eR|JbBCj4+PxClq+JjULK zl=4K(fTuJVC#jKiq6iB?;t+-z<=kexcrlaC4I=>wlkyEJ0Zo$~4l;j5Y8B|^VN9_9 zOWNuU3*_TtHji+)Ku0kDh=yvKB@Mc?B*Fjt|Nq~Aqrm`z(=0?K%Fu#{e;W+Y+h`hN zpMd75m9=bVAbuIHn(RWCBn+7MAzcYTw3Ol$Q<$%L6q6aaJ=X+XQ%iiK>lyRKO9HKu{u zRe?aW40@EGrVi^Ny21e`_Z$@~bMnAyE{k1~HW`Ub9JVR!op1dgEDANx<5uw zL!QLx0jqFCnPKpMl|P#uRNEa04#w!@N*+8Ri9~wX%0E|ULhOlj*fSguZWt_WHR14l zvWr-(=)|6M2#^Y5#p8?c{uuoSOVB*w0$qO+gwbG7n8?8ZUeAd@Nrc3Vf^(i

(xt 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 Date: Thu, 18 Dec 2025 15:18:09 +0400 Subject: [PATCH 4/5] Move Miro logo to centralized Logos directory - Move logo from Solutions/Miro/Logo/Miro.svg to Logos/Miro.svg to follow repository convention - Update Solution_Miro.json to reference centralized logo: https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Logos/Miro.svg - Delete the now-empty Solutions/Miro/Logo directory - Rebuild solution package with V3 tool to reflect logo URL change This ensures the logo file exists on master branch when referenced, fixing logo-validation workflow failure. --- Logos/Miro.svg | 4 ++++ Solutions/Miro/Data/Solution_Miro.json | 2 +- Solutions/Miro/Package/3.0.0.zip | Bin 12540 -> 12541 bytes .../Miro/Package/createUiDefinition.json | 2 +- Solutions/Miro/Package/mainTemplate.json | 2 +- 5 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 Logos/Miro.svg diff --git a/Logos/Miro.svg b/Logos/Miro.svg new file mode 100644 index 00000000000..169efff82ec --- /dev/null +++ b/Logos/Miro.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Solutions/Miro/Data/Solution_Miro.json b/Solutions/Miro/Data/Solution_Miro.json index 90e89d1aee7..106e92b744a 100644 --- a/Solutions/Miro/Data/Solution_Miro.json +++ b/Solutions/Miro/Data/Solution_Miro.json @@ -1,7 +1,7 @@ { "Name": "Miro", "Author": "Miro - enterprise_integrations@miro.com", - "Logo": "", + "Logo": "", "Description": "The [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).\n\n**Underlying Microsoft technology used:**\n\nThis solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\n• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector)", "Data Connectors": [ "Data Connectors/MiroAuditLogs_CCF/MiroAuditLogs_DataConnectorDefinition.json", diff --git a/Solutions/Miro/Package/3.0.0.zip b/Solutions/Miro/Package/3.0.0.zip index cc3ad968fcf29172b3347fae2d10993801ca398e..e6c19ddcc0b36d0b19571e95ef98219bfa2bbf50 100644 GIT binary patch delta 2000 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 diff --git a/Solutions/Miro/Package/createUiDefinition.json b/Solutions/Miro/Package/createUiDefinition.json index fd3ca5c726f..cc3c72ebdc0 100644 --- a/Solutions/Miro/Package/createUiDefinition.json +++ b/Solutions/Miro/Package/createUiDefinition.json @@ -6,7 +6,7 @@ "config": { "isWizard": false, "basics": { - "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Miro/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).\n\n**Underlying Microsoft technology used:**\n\nThis solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\n• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector)\n\n**Data Connectors:** 2\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Miro/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Miro](https://miro.com/) solution for Microsoft Sentinel provides the capability to ingest audit logs and content activity logs from [Miro REST APIs](https://developers.miro.com/reference) into Microsoft Sentinel using the Codeless Connector Framework (CCF). This connector enables organizations to monitor and analyze activities within their Miro workspaces. For detailed instructions, refer to the [documentation](https://help.miro.com/hc/en-us/articles/31325908249362).\n\n**Underlying Microsoft technology used:**\n\nThis solution is dependent on the following technology and this dependency may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\n• [Codeless Connector Framework (CCF)](https://learn.microsoft.com/azure/sentinel/create-codeless-connector)\n\n**Data Connectors:** 2\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", "subscription": { "resourceProviders": [ "Microsoft.OperationsManagement/solutions", diff --git a/Solutions/Miro/Package/mainTemplate.json b/Solutions/Miro/Package/mainTemplate.json index c482d9bc6d8..93fb64f8066 100644 --- a/Solutions/Miro/Package/mainTemplate.json +++ b/Solutions/Miro/Package/mainTemplate.json @@ -1459,7 +1459,7 @@ "contentKind": "Solution", "contentProductId": "[variables('_solutioncontentProductId')]", "id": "[variables('_solutioncontentProductId')]", - "icon": "", + "icon": "", "contentId": "[variables('_solutionId')]", "parentId": "[variables('_solutionId')]", "source": { From 1b5e69ffd97af2f1c3833728a7eaa6c0eae1542c Mon Sep 17 00:00:00 2001 From: Ilia Sretenskii Date: Thu, 18 Dec 2025 15:59:45 +0400 Subject: [PATCH 5/5] Delete old solution-specific Miro logo location The logo has been moved to the centralized Logos directory. Removing the now-unused Solutions/Miro/Logo/Miro.svg file. --- Solutions/Miro/Logo/Miro.svg | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 Solutions/Miro/Logo/Miro.svg diff --git a/Solutions/Miro/Logo/Miro.svg b/Solutions/Miro/Logo/Miro.svg deleted file mode 100644 index 169efff82ec..00000000000 --- a/Solutions/Miro/Logo/Miro.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -