StratusGrid Knowledge Base | Your Source for AWS Cloud Expertise

Onboard Microsoft Azure to Stratusphere

Written by Trevor Sullivan | Jan 13, 2025 1:53:28 PM

After configuring Single Sign-On (SSO) for Stratusphere, you can add a Microsoft Azure data source to your Stratusphere organization. The Azure data source uses Entra ID to authenticate to your tenant via an App Registration & Service Principal. Authentication is handled using a public/private certificate key pair. We assign the built-in Reader role to your Tenant Root Group, which enables identification of cost optimization and security findings.

Prerequisites

  1.  Ensure that your Microsoft Entra ID user account is able to assign permissions to Azure Management Groups.
    1. Open Entra ID in the Azure Portal

    2. Go to Manage ➡️ Properties

    3. Enable the "can manage access to all Azure subscriptions and management groups in this tenant" option

  2.  Please share the Azure subscription ID where you'll be creating the necessary Stratusphere resources (Storage Account).
  3.  You'll need a couple of values, generated by StratusGrid, for the onboarding process:
    1. API token for the Stratusphere data API

    2. Public key certificate, used for Entra ID authentication

       

Create Azure App Registration

The identity used by Stratusphere to analyze your cloud environment is called an App Registration in Entra ID. This identity can be created using the Microsoft Azure CLI tool. You can access the Azure CLI from the built-in CloudShell environment in the Azure Portal, if you don't have it installed locally.

To open the Azure CloudShell, simply open the Azure Portal and click on the Shell icon, next to the bell icon, in the top-right navigation bar. Then click PowerShell, select an Azure Subscription to use for Stratusphere deployment, and click the Apply button.

Next, replace the IMPORTANT line below with the public key provided by StratusGrid, and run the following script.

 
$Account = az account show | ConvertFrom-Json

$NewApp = az ad app create --display-name stratusgrid-stratusphere
$App = $NewApp | ConvertFrom-Json

# Delete the Service Principal (if it exists) and re-create it with a new GUID
$ServicePrincipal = az ad sp create --id $App.appId | ConvertFrom-Json

az role assignment create --assignee $App.appId `
--role Reader `
--scope "/providers/Microsoft.Management/managementGroups/$($Account.tenantID)"

@'
IMPORTANT: REPLACE THIS LINE WITH THE PUBLIC KEY GENERATED BY STRATUSGRID
'@ | Out-File -Path publickey.pem
az ad app credential reset --id $App.appId --cert '@publickey.pem'

$Text = @'
Please copy/paste this information to StratusGrid:

TenantID: {0}
SubscriptionID: {1}
App Registration ID: {2}
Service Principal ID: {3}
'@ -f $Account.tenantId, $Account.id, $App.appId, $ServicePrincipal.id
Write-Host -Object $Text -ForegroundColor Green

Deploy Azure Resource Manager (ARM) JSON Template

Stratusphere needs an Azure Storage Account, to ingest billing data from, and an Event Grid subscription to notify when new data is available. These resources are deployed through an Azure Resource Manager (ARM) JSON template.

  • Open the Azure Portal
  • Search for Deploy a Custom Template
  • Click the Build Your Own Template in the Editor option
  • Copy and paste the ARM template below
  • Click the Save, then the Next button
  • On the Basics screen
    • Specify the Resource Group to deploy to (create one)
    • Specify the Stratusphere API token parameter
    • Specify the Service Principal ID parameter
  • Click Review & Create, then Create
 
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"stratusphereTopicName": {
"type": "string",
"defaultValue": "stratusgrid-stratusphere"
},
"storageAccountNamePrefix": {
"type": "string",
"defaultValue": "sgstratusphere"
},
"containerName": {
"type": "string",
"defaultValue": "cme"
},
"location": {
"type": "string",
"defaultValue": "eastus"
},
"webhookURL": {
"type": "string",
"defaultValue": "https://data.stratusphere.app/azure/cme"
},
"stratusphereAPIToken": {
"type": "securestring"
},
"servicePrincipalId": {
"type": "string",
"metadata": {
"description": "This is the Service Principal ID associated with the Entra ID App Registration previously created. Please ensure you use the Service Principal ID property, not the App ID."
}
}
},
"variables": {
"dataSourceId": "[take(replace(subscription().subscriptionId,'-',''), 10)]",
"storageAccountName": "[concat(parameters('storageAccountNamePrefix'), variables('dataSourceId'))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[variables('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2023-01-01",
"name": "[format('{0}/{1}', variables('storageAccountName'), 'default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
]
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2023-01-01",
"name": "[format('{0}/{1}/{2}', variables('storageAccountName'), 'default', parameters('containerName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('storageAccountName'), 'default')]"
]
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id)]",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]",
"principalId": "[parameters('servicePrincipalId')]"
}
},
{
"type": "Microsoft.EventGrid/systemTopics",
"apiVersion": "2022-06-15",
"name": "[parameters('stratusphereTopicName')]",
"location": "eastus",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', variables('storageAccountName'), 'default', parameters('containerName'))]"
],
"properties": {
"source": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
"topicType": "Microsoft.Storage.StorageAccounts"
}
},
{
"type": "Microsoft.EventGrid/systemTopics/eventSubscriptions",
"apiVersion": "2022-06-15",
"name": "[concat(parameters('stratusphereTopicName'), '/', parameters('stratusphereTopicName'), '-webhook')]",
"dependsOn": [
"[resourceId('Microsoft.EventGrid/systemTopics', parameters('stratusphereTopicName'))]"
],
"properties": {
"destination": {
"properties": {
"maxEventsPerBatch": 10,
"preferredBatchSizeInKilobytes": 64,
"endpointUrl": "[parameters('webhookURL')]",
"deliveryAttributeMappings": [
{
"properties": {
"value": "[concat('Basic ', parameters('stratusphereAPIToken'))]",
"isSecret": true
},
"name": "Authorization",
"type": "Static"
}
]
},
"endpointType": "WebHook"
},
"filter": {
"subjectEndsWith": "manifest.json",
"includedEventTypes": [
"Microsoft.Storage.BlobCreated"
],
"enableAdvancedFilteringOnArrays": true
},
"labels": [],
"eventDeliverySchema": "CloudEventSchemaV1_0",
"retryPolicy": {
"maxDeliveryAttempts": 30,
"eventTimeToLiveInMinutes": 1440
}
}
}
]
}

Create the Cost Management Export

To create the Cost Management Export with the Microsoft Azure Portal, follow these steps.

  • Open the Microsoft Azure Portal
  • Navigate to the desired Azure Subscription
  • Search for Cost Exports in the search bar
  • Click the Create button
  • Click the Create Your Own Export option
  • Select the Datasets tab
    • For Export Prefix, enter stratusphere
    • Click the Add Export button
      • For Type of Data, choose Cost and Usage Details (actual) option
      • Give the export the name stratusgrid-stratusphere-export
      • For Dataset Version, select the 2021-10-01 option
      • For Frequency, choose the Daily Export of Month-to-Date Costs option
  • Select the Destination tab
    • For Storage Type, choose the Azure Blob Storage option
    • For Destination and Storage, choose Use Existing
    • Select the Subscription and Storage Account for Stratusphere
    • For Container, type cme
    • For Directory, type actual
    • For Format, choose the Parquet option
    • For the Compression Type, choose the Snappy option
  • Click Review and Create, then the Create button
 
Potential Issues and Resolutions

Invalid API Token

If an invalid Stratusphere API token is provided as input to the ARM template deployment, you may receive the following error message.

ERROR: Webhook validation handshake failed for https://data.stratusphere.app/azure/cme. Http OPTIONS request failed with response code Unauthorized. For troubleshooting, visit https://aka.ms/esvalidationcloudevent. Activity id:ec08ccbd-6395-4499-b04f-2e3045e9e484, timestamp: 12/16/2024 10:13:21 PM (UTC).

Resolution: If this scenario occurs, please be sure you request a valid API token from the StratusGrid team. You can click the Redeploy button on the Deployment Overview page, and then follow the directions to deploy the template again.