How to Onboard an Azure CSP Indirect Subscription

Learn how to onboard an Azure CSP Indirect Subscription available under an Azure CSP Indirect Reseller (Tier 2).

Introduction

This user guide will explain how you can onboard an Azure CSP Indirect Subscription available under an Azure CSP Indirect Reseller (Tier 2).

Pre-onboarding

There are certain prerequisites that need to be setup in your Azure CSP Indirect Subscription before it can be onboarded into CoreStack.

CoreStack uses the Daemon Application scenario with Client Credentials flow for OAut2.0 flow and grant type, as depicted here in this user guide. The Client Credential flow requires a valid application registration to be created for a specific Azure subscription in order to successfully allow access to the required Azure resources.

To onboard your Azure subscription into CoreStack, the following values must be generated/copied from your Azure console and configured in CoreStack:

  1. Application ID and Tenant ID
  2. Application Secret
  3. Access Validation

As you retrieve each of these values, keep them ready in a notepad to be able to copy/paste in CoreStack when you begin the onboarding steps.

Step 1: Fetch the Application ID and Tenant ID

  1. In the Azure Portal, navigate to Azure Active Directory > App registrations > New registration. The Register an application screen appears.
  1. On the left pane, click App registration and click + New registration.
  1. In the Name box, type a name for the application, for example, CoreStack.App.

The other fields can be left with their default options selected.

  • The value of the Supported account types field can be Single Tenant.
  • The value of the Redirect URI field can be blank.
  1. Click Register.

The application will be registered, and the Application (client) ID and Directory (tenant) ID will be displayed on the Overview screen.

Copy the Application ID and the Tenant ID and paste the details into a notepad.

Step 2: Fetch Application Secret

The Application Secret is the password or key that you need to provide for the specific app that was just created.

  1. On the Overview screen, click Certificates & secrets.
  2. Click + New client secret.
  3. Provide a description and expiry duration for the secret. You can leave the duration with the default value of 1 year. You can revoke this anytime later, if required.
  4. Click Add. The Client secret will be created and displayed.

📘

Note:

Ensure that you copy this secret value and paste it in a notepad, since you cannot retrieve this later.

Step 3: Access Validation

Perform the following steps to register the resource providers:

  1. Navigate to the subscription that you want to onboard in CoreStack and select the subscription > Settings > Resource providers.
  2. Search for the following resource providers and register them if they are not registered before:
    • Microsoft.Authorization
    • Microsoft.Billing
    • Microsoft.Commerce
    • Microsoft.Consumption
    • Microsoft.CostManagement

Step 4: IAM Access for App

The app that is created in Step 1 must have the required level of access within the subscription. To provide this access, follow the below steps:

  1. In the Azure Portal, navigate to Subscriptions .

  2. Click Access Control (IAM).

  3. Click + Add and then click to select Add role assignment. The Add role assignment screen appears.

  1. Select Job function roles if you plan to use the Assessment Only onboarding option in CoreStack.
  1. Select the Reader role for the Assessment Only option.
  1. Select the privileged administrator roles if you plan to use the Assessment + Governance onboarding option in CoreStack.
  1. Select Contributor for the Assessment + Governance option.
  1. Additionally, if you plan to use the Assessment + Governance option in CoreStack, then select job function roles next.
  1. Select the Resource Policy Contributor for the Assessment + Governance option.
  1. In the Assign access to field, ensure that the User, group, or service principal option is selected.

  2. Click + Select members and in the Select field, search and select the app that was created earlier. In this example below, we'll select CoreStack.App.

  1. Click the Save button to assign the role.

After the role is assigned, it will be listed in the Role Assignments tab.

📘

Note:

The "Resource Policy Contributor" role assignment is required only if you intend to use CoreStack to create policies for your Azure subscription.

Step 5: Reservation Reader Role

🚧

Note:

  • You can skip this step if you don’t have any reserved instances in your subscription.
  • For CSP Indirect subscriptions, users cannot fetch the reservations directly due to restriction from Azure. If there are any reservations applied within these subscriptions, then users need to get the necessary billing related permissions (Billing Reader) from the CSP partner to service principal, which was used while onboarding. Only after this, users will be able to fetch the required reservations data.

📘

Note:

Be sure to update the Reservation Reader role that will be required for assigning roles to tenants.  Perform the following steps to update the Reservation Reader role: 

  1. Navigate to Microsoft Enterprise ID > Properties in Azure. 

  2. In the Access Management for Azure resources field, toggle the button to enable it. 

  3. After enabling it, log out from the Azure portal and log back in to ensure that the changes are reflected. 

The platform requires the Reservation Reader role for CoreStack.App in order to fetch the reserved instances in the subscription.

  1. Navigate to Virtual machines > Reservations > View.

You can now see all the reserved instances in your subscription.

  1. Click Role Assignment.
  1. Click +Add and then click Add role assignment.
  1. In the Assignment type field, select Job function roles.
  1. In the Search box, type Reservations Reader and select it from the search result and then click Next.
  1. Ensure that the User, group, or service principal option is selected in the Assign access to field.

  2. Search and select the app that was created earlier. In this example, we'll select CoreStack.App in the Select field.

  3. Click the Save button to assign the role.

Copy all these details and provide them while onboarding your Azure Subscription into CoreStack.

Account Onboarding Using PowerShell Script

Overview

Users can utilize a PowerShell script that simplifies the process of onboarding new accounts into the platform by automating several critical steps. This allows for an efficient and error-free operation, ensuring that all required components are properly configured without the need for any manual intervention.

The steps involved in the onboarding process are:

  1. Selecting Azure Subscriptions
  2. Assigning roles
  3. Creating a service principal
  4. Registering the necessary resource providers

Prerequisites

Before going ahead with the automated process of onboarding Azure accounts, users must check for the following prerequisite conditions.

  1. First, check whether the Azure PowerShell module is installed. Run the command below to check for the Azure PowerShell module.
    Get-Module -Name Az -ListAvailable
    
    • If Azure PowerShell module is not installed, then install it by running:
     Install-Module -Name Az -AllowClobber -Scope CurrentUser  
     Import-Module Az
    
  2. Next, run the command below to check whether AzureAD module is installed.
     Get-Module -Name AzureAD -ListAvailable
    
    • If AzureAD module is not listed, then install it by running:
    Install-Module -Name AzureAD -AllowClobber -Scope CurrentUser
    Import-Module AzureAD
    
  3. Users must have the appropriate permissions (i.e. Owner-level access in Subscription) to create applications and assign roles in Azure.

Script Description

The PowerShell script performs the following main tasks:

  1. Create a Service Principal: Facilitates the creation of a new service principal in Azure AD with a display name provided by the user.
  2. Select Azure Subscriptions: Allows the user to select one or multiple Azure Subscriptions or choose all enabled Subscriptions.
  3. Assign Roles to Service Principal: Assigns the selected roles (like Reader, Contributor, etc.) to the service principal across chosen Subscriptions.
  4. Register Azure Resource Providers: Registers a predefined list of Azure resource providers necessary for operations in the platform.

Refer to the PowerShell script below that can be used for onboarding.

# Function to create Service Principal and generate a secret
Connect-AzureAD
function Create-ServicePrincipal {
    $displayName = Read-Host "Please enter a display name for the new Service Principal"
    if ([string]::IsNullOrWhiteSpace($displayName)) {
        Write-Host "No display name provided. Exiting function."
        return $null
    }
    try {
        $application = New-AzureADApplication -DisplayName $displayName
        Write-Host "Application created with ID: $($application.AppId)"
        
        $servicePrincipal = New-AzureADServicePrincipal -AppId $application.AppId
        Write-Host "Service Principal created with Application ID: $($application.AppId)"
        
        $startDate = Get-Date
        $endDate = $startDate.AddYears(1)
        $passwordCredential = New-AzureADApplicationPasswordCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "Access" -StartDate $startDate -EndDate $endDate
        Write-Host "Secret created for Application. Value: $($passwordCredential.Value)"
        
        # Fetch tenant ID
        $tenantId = (Get-AzureADTenantDetail).ObjectId
        Write-Host "Tenant ID: $tenantId"
        
        return $application, $servicePrincipal, $passwordCredential, $tenantId
    } catch {
        Write-Host "Failed to create service principal or secret: $_"
        return $null
    }
}

# Example of calling the function
$application, $servicePrincipal, $secret, $tenantId = Create-ServicePrincipal
 Start-Sleep -Seconds 10
 #Function to list and select the subscriptions
 function Select-Subscription {
    param (
        [string]$title,
        [array]$subscriptions
    )
    Write-Host $title
    for ($i = 0; $i -lt $subscriptions.Count; $i++) {
        Write-Host "$($i+1) : $($subscriptions[$i].name) - $($subscriptions[$i].id)"
    }
    # Adding an option for selecting all subscriptions
    Write-Host "$($subscriptions.Count + 1) : All Subscriptions"
    $indices = Read-Host "Enter the indices of the subscriptions (comma separated, or select 'All'):"
    # Check if the user selected "All"
    if ($indices -eq $($subscriptions.Count + 1)) {
        return $subscriptions
    }
    else {
        $selectedIndices = $indices -split ',' | ForEach-Object { [int]$_ - 1 }
        $selectedSubscriptions = $selectedIndices | ForEach-Object { $subscriptions[$_] }
        return $selectedSubscriptions
    }
}
# Assuming $subs is a JSON string from the output of `az account list`
$subs = az account list --query "[?state=='Enabled']" --only-show-errors
$subs_ids = $subs | ConvertFrom-Json
$selectedSubscription = Select-Subscription -title "Please select a subscription:" -subscriptions $subs_ids
# Displaying the selected subscriptions
foreach ($sub in $selectedSubscription) {
    Write-Host "Selected subscription: $($sub.name) - $($sub.id)"
}
$selectedSubscription | Format-Table -Property Name, Id, State, IsDefault -AutoSize
#Function to define the roles
function Show-Menu {
    param (
        [string]$title,
        [hashtable]$menuItems,
        [bool]$allowMultiple = $false
    )
    Write-Host "`n$title"
    $menuItems.Keys | Sort-Object | ForEach-Object { Write-Host "$_ : $($menuItems[$_])" }
    if ($allowMultiple) {
        $input = Read-Host "Enter choices separated by commas (e.g., 1,2)"
        $choices = $input -split ',' | ForEach-Object { $_.Trim() }
    } else {
        $choices = @(Read-Host "Enter choice")
    }
    $selectedItems = $choices | ForEach-Object { $menuItems[$_] }
    return $selectedItems
}
# Define the possible role definitions in a hashtable
$roleDefinitions = @{
    "1" = "Reader"
    "2" = "Contributor"
    "3" = "Resource Policy Contributor"
}
# Display menu and get user choices
$selectedRoles = Show-Menu -title "Select Role Definitions" -menuItems $roleDefinitions -allowMultiple $true
# Display the selected roles
$selectedRoles | ForEach-Object { Write-Host "- $_" }
#Assining the role to the selected subscriptions 
foreach ($sub in $selectedSubscription) {
    $context = Set-AzContext -SubscriptionId $sub.id -ErrorAction SilentlyContinue
    if ($context) {
        Write-Host "Switched to subscription: $($sub.name)"
        # Assign each selected role to the service principal for the subscription
        foreach ($role in $selectedRoles) {
            try {
                # Make sure to use ServicePrincipal ObjectId
                $roleAssignment = New-AzRoleAssignment -ObjectId $servicePrincipal.ObjectId -RoleDefinitionName $role -Scope "/subscriptions/$($sub.id)" -ErrorAction Stop
                Write-Host "Successfully assigned $role to service principal $($servicePrincipal.AppId) in subscription $($sub.name)"
            } catch {
                Write-Host "Failed to assign $role to service principal $($servicePrincipal.AppId) in subscription $($sub.name): $_"
            }
        }
    }
}
#Registering the Mandatory Resources Providers for the selected subscription/subscriptions
$resourceProviders = @(
    "Microsoft.Authorization",
    "Microsoft.Billing",
    "Microsoft.Commerce",
    "Microsoft.Consumption",
    "Microsoft.CostManagement",
    "Microsoft.Insights",
    "Microsoft.Network",
    "Microsoft.PolicyInsights",
    "Microsoft.Security",
    "Microsoft.Compute",
    "Microsoft.ContainerInstance",
    "Microsoft.ContainerRegistry",
    "Microsoft.ContainerService",
    "Microsoft.DBforMySQL",
    "Microsoft.DBforPostgreSQL",
    "Microsoft.DevTestLab",
    "Microsoft.RecoveryServices",
    "Microsoft.SQL",
    "Microsoft.Storage",
    "Microsoft.Web"
)
foreach ($sub in $selectedSubscription) {                                        
    # Set the Azure context to the current subscription in the loop
    $context = Set-AzContext -SubscriptionId $sub.id -ErrorAction SilentlyContinue
	# Pause after setting the context to ensure it has been applied
	Start-Sleep -Seconds 10  
    if ($context) {
        Write-Host "Switched to subscription: $($sub.name)"
        # Now perform actions on the current subscription
        foreach ($provider in $resourceProviders) {
            try {
                $status = Get-AzResourceProvider -ProviderNamespace $provider
                if ($status.RegistrationState -eq "Registered") {
                    Write-Host "Resource provider $provider is already registered in $($sub.name)."
                } else {
                    Register-AzResourceProvider -ProviderNamespace $provider | Out-Null
                    Write-Host "Registered resource provider: $provider in $($sub.name)"
					# Wait after registering a provider to ensure the operation completes
					Start-Sleep -Seconds 20  
                }
            } catch {
                Write-Host "Failed to retrieve or register the resource provider $provider in $($sub.name). Error: $_"
            }
        }
    } else {
        Write-Host "Failed to set context to subscription: $($sub.name)"
    }
}
exit-PSSession

Onboarding Steps

Perform the following steps to complete the onboarding process for Azure cloud accounts using the PowerShell script:

  1. To create a service principal, when prompted, enter a display name for a new Azure AD application and service principal.

    The script creates the application and service principal, and generates a secret key valid for one year. You can view the tenant ID, application ID, and secret value (Note: We strongly recommend copying these values down in a notepad).

  2. When prompted, enter the indices of the Azure subscription account(s) for onboarding separated by commas, or choose all subscriptions by entering a special index.

  3. When prompted, select one or more roles to assign to the service principal. It then assigns the selected roles to the service principal for each chosen Subscription.

  4. The script automatically attempts to register a set of required Azure resource providers if they are not already registered.

❗️

Error Handling:

The script includes error handling to provide feedback if any operation(s) fail, such as role assignments or resource provider registration.

Onboarding an Azure CSP Indirect Subscription

The following steps need to be performed to onboard an Azure CSP Indirect Subscription in the CoreStack application:

  1. Sign in to the CoreStack application.
  2. On the CoreStack Account Governance dashboard, click Add New, select Single Account, and then click Start Now. The onboarding screen appears.
  1. In the Public Cloud field, select Azure and click Get Started.
  1. In the Access Type field, select the required option. The options are: Assessment and Assessment + Governance.
  1. In the Azure Environment field, select your preferred option. The options are: Azure Global, Azure China, and Azure Government.
  2. In the Currency drop-down list, click to select the required currency.
  3. In the Environment drop-down list, click to select the appropriate option. The options are: Production, Staging, QA, and Development.
  4. Click Next.
  1. Provide the details for other fields (Tenant ID, Application ID, Application Secret) as explained in the Pre-onboarding section.
  2. Click Validate.

The Advanced Settings section will be displayed with additional fields (Name, Subscription, Subscription Type, Parent Account, and Scope).

  1. In the Name field, modify the pre-populated name of the account, if required.
  2. In the Subscription drop-down list, select the required subscription.
  3. In the Subscription Type field, select the Azure CSP-InDirect option.
  4. In the Scope field, select the required option. The options are: Account, Private, and Tenant.
  1. Click I’m Done.

The Azure Subscription will then be onboarded successfully into CoreStack. Relevant insights and information about the resources available in the account will be populated under each of the cloud governance pillars in CoreStack.

Post Onboarding Access Validation

Perform the following steps to validate the allowed permissions:

  1. Navigate to the Account Governance page.
  2. Select the subscription that is onboarded and click VIEW > View Settings.
  1. Click Access Validation > Cost and verify the below permissions to fetch the cost.
    • Microsoft.Authorization
    • Microsoft.Billing
    • Microsoft.Commerce
    • Microsoft.Consumption
    • Microsoft.CostManagement

Why are these Permissions Required?

CoreStack requires Contributor access to the following Service Providers. However, the account owner can restrict access to specific services that will only be managed through CoreStack.

The following table explains the need for access to the service along with the rationale:

Azure ProviderProduct/CategoryReader Access (For Discovery)Contributor Access (For Actions)
Microsoft.ComputeVirtual Machines

Virtual Machines Scale Sets

Virtual Machines Sizes

Availability Sets

Image Publishers

Images

Disks
MandatoryMandatory
Microsoft.ContainerInstanceContainer GroupsPreferredOptional
Microsoft.ContainerRegistryContainer RegistryPreferredOptional
Microsoft.ContainerServiceContainer Service

Kubernetes
PreferredOptional
Microsoft.StorageStorage accounts

Storage Snapshots
MandatoryMandatory
Microsoft.RecoveryServicesRecovery VaultPreferredOptional
Microsoft.NetworkRoute Tables

Network Security Group

Virtual Networks

Public IP Address

Traffic Manager Profiles

Load Balancer

Express Routes

Application Gateway

Application Gateway

Available SSL Policy
MandatoryMandatory
Microsoft.SqlSQLPreferredOptional
Microsoft.DBforPostgreSQLPGSQLPreferredOptional
Microsoft.DBforMySQLMysqlPreferredOptional
  • Preferable: Access is not mandatory. However, some of the automation features will not be functional without the required access. You can exclude them for “Assessment-Only”.
  • Optional: Not mandatory, similar to that of Preferable, core features will continue to work. Some low-level actions will have an Impact. You can exclude them for “Assessment-Only”.
  • Mandatory: Non-negotiable, even to onboard account with read-only permissions (“Assessment-Only”), these access details would be needed.

Impact on the Azure Subscription

If you intend to use CoreStack for remediation and automation, CoreStack creates resources and applies some configurations in Azure while configuring these capabilities in CoreStack.

Alert Rules and Alert Actions

Alert rules will be created when monitoring thresholds configured as part of the Operations – Alerts module.

A new alert action will be added to the created rules to invoke CoreStack notification webhook when threshold alert is triggered.

Azure Policy

CoreStack will create the Policy Definitions and Assignments based on the GuardRails you prefer to set up for your Azure Subscription.

Security Center

CoreStack will enable the Free-tier or Standard Tier for the resources based on the security configurations (Enabling Standard Tier has cost implications, please exercise caution during configuration).

Billing Impact due to CoreStack Onboarding

There is no billing impact as such in configuring your account with CoreStack until certain services are consumed through CoreStack.

The following are the few areas where there might be cost implications:

FeatureFree Units IncludedPriceCS Remarks
Alert Notifications100,000 web hooks per month$0.60/1,000,000 web hooksNone
Dynamic ThresholdsNone$0.10 per dynamic threshold per monthCoreStack does not create Dynamic Thresholds as part of account onboarding. However, you can configure through Operations template, if required.
Azure Security CenterFree TierPricing varies per resource type.Standard Tier if opted will have higher cost impact.
Refer Azure pricing page for more details.
Monitoring Metrics10 monitored metric time-series per month$0.10 per metric time-series monitored per monthNone