diff --git a/13-Tenant Security Solution Setup/Readme.md b/13-Tenant Security Solution Setup/Readme.md index 4e5139e4..635c0f1f 100644 --- a/13-Tenant Security Solution Setup/Readme.md +++ b/13-Tenant Security Solution Setup/Readme.md @@ -1,13 +1,14 @@ # Azure Tenant Security Solution (AzTS) [In Preview] -## Azure Tenant Security -### Contents -- [Overview](Readme.md#overview) -- [Why Azure Tenant Security Solution?](Readme.md#why-tenant-security-solution) -- [Setting up Azure Tenant Security Solution - Step by Step](Readme.md#setting-up-tenant-security-solution---step-by-step) -- [Tenant Security Solution - under the covers (how it works)](Readme.md#tenant-security-solution---under-the-covers-how-it-works) -- [Create compliance and monitoring solutions](Readme.md#create-security-compliance-monitoring-solutions) -- [Feedback](Readme.md#feedback) +### [Overview](Readme.md#overview) +### [Why Azure Tenant Security Solution?](Readme.md#why-tenant-security-solution) +### [Setting up Azure Tenant Security Solution - Step by Step](Readme.md#setting-up-tenant-security-solution---step-by-step) + - [Installing AzTS Solution](Readme.md#1-installing-AzTS-Solution) + - [Verifying that Tenant Security Solution installation is complete](Readme.md#2-verifying-that-tenant-security-solution-installation-is-complete) + - [Visualization for AzTS scan result](Readme.md#3-visualization) +### [Tenant Security Solution - under the covers (how it works)](Readme.md#tenant-security-solution---under-the-covers-how-it-works) +### [Create compliance and monitoring solutions](Readme.md#create-security-compliance-monitoring-solutions) +### [Feedback](Readme.md#feedback) ----------------------------------------------------------------- ## Overview @@ -21,15 +22,20 @@ The AzTS Solution was created with the following explicit objectives (some of wh * Enable incremental transition of our controls from custom code to Azure/ASC policy-based approach (using ASC/policy-based controls where available today and continue to migrate as more controls become available) ## Setting up Azure Tenant Security Solution - Step by Step -In this section, we will walk through the steps of setting up AzTS Solution. + ![ProgressBar](../Images/12_TSS_ProgressBar1.png) -**Note:** You can download execution script present [here](https://github.com/azsk/DevOpsKit-docs/raw/users/TenantSecurity/13-Tenant%20Security%20Solution%20Setup/Scripts/ExecutionScript.ps1) which has all commands mentioned in below steps + +## 1. Installing AzTS Solution + +In this section, we will walk through the steps of setting up AzTS Solution. This setup can take up to 30 minutes. + +**Note:** You can download execution script present [here](Scripts/ExecutionScript.ps1?raw=1) which has all commands mentioned in below steps Setup is divided into five steps: -**1. Validate prerequisites on machine** +**Step 1 of 6. Validate prerequisites on machine** i) Installation steps are supported using following OS options: @@ -45,7 +51,7 @@ Setup is divided into five steps: ![PowerShell Version](../Images/00_PS_Version.PNG) -**2. Installing Az Modules:** +**Step 2 of 6. Installing Az Modules:** Az modules contains cmdlet to deploy Azure resources. These cmdlets is used to create AzTS scan solution resources with the help of ARM template. Install Az Powershell Modules using below command. @@ -57,6 +63,8 @@ Install-Module -Name Az.Accounts -AllowClobber -Scope CurrentUser -repository PS Install-Module -Name Az.Resources -AllowClobber -Scope CurrentUser -repository PSGallery Install-Module -Name Az.Storage -AllowClobber -Scope CurrentUser -repository PSGallery Install-Module -Name Az.ManagedServiceIdentity -AllowClobber -Scope CurrentUser -repository PSGallery +Install-Module -Name Az.Monitor -AllowClobber -Scope CurrentUser -repository PSGallery + ``` ``` Powershell @@ -64,120 +72,233 @@ Install-Module -Name Az.ManagedServiceIdentity -AllowClobber -Scope CurrentUser Install-Module -Name AzureAD -AllowClobber -Scope CurrentUser -repository PSGallery ``` -**3. Setting up scanning identity** + +**Step 3 of 6. Download and extract deployment package** + + Deployment packages mainly contains + ARM template: Contains resource configuration details that needs to be created as part of setup + Deployment setup script: Provides the cmdlet to run installation. + +i) Download deployment package zip from [here](TemplateFiles/DeploymentFiles.zip?raw=1) to your local machine. + +ii) Extract zip to local folder location + +iii) Unblock the content. Below command will help to unblock files. + +``` PowerShell +Get-ChildItem -Path "" -Recurse | Unblock-File +``` + +iv) Point current path to deployment folder and load AzTS setup script +``` PowerShell +# Point current path to extracted folder location and load setup script from deploy folder + +CD "\DeploymentFiles" + +# Load AzTS Setup script in session +. ".\AzTSSetup.ps1" + +# Note: Make sure you copy '.' present at the start of line. + +``` + +[Back to top…](Readme.md#contents) + +**Step 4 of 6. Setting up scanning identity** The AzTS setup basically provisions your subscriptions with the ability to do daily scans for security controls. To do the scanning, it requires a [User-assigned Managed Identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) (central scanning identity owned by you) and 'Reader' access to target subscriptions on which scan needs to be performed. Before creating user-assigned managed identity, please connect to AzureAD and AzAccount with the tenant Id where you want to use AzTS solution. - ``` Powershell + +# Clear existing login, if any + +Disconnect-AzAccount +Disconnect-AzureAD + +# Connect to AzureAD and AzAccount + Connect-AzAccount -Tenant Connect-AzureAD -TenantId ``` -i) You can create user-assigned managed identity with below PowerShell command or Portal steps [here](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-portal) +i) You can create user-assigned managed identity (MI) with below PowerShell command or Portal steps [here](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-portal). This PowerShell command assigns 'Reader' access to user-assigned managed identity on target subscriptions. You need to be 'Owner' on target subscription to perform role assignment. ``` Powershell -# Step 1: Set context to subscription where user-assigned managed identity needs to be created -Set-AzContext -SubscriptionId +# Subscription id in which scanner MI needs to be created. +$MIHostingSubId = "" -# Step 2: Create resource group where user-assigned MI resource will be created. -New-AzResourceGroup -Name -Location +# Resource group name in which scanner MI needs to be created. +$MIHostingRGName = "" -# Step 3: Create user-assigned managed identity -$UserAssignedIdentity = New-AzUserAssignedIdentity -ResourceGroupName -Name +# Location in which scanner MI needs to be created. +# Note: For better performance, we recommend hosting the MI and resources setup using AzTS Soln installation command in one location. +$Location = "" -# Step 4: Save resource id generated for user identity using below command. This will be used in AzTS Soln installation. +# Name of the scanner MI. +$MIName = "" + +# List of target subscription(s) that needs to be scanned by AzTS. This command assigns reader access to user-assigned managed identity on target subscriptions. Add target subscriptionds in place of +$TargetSubscriptionIds = @("","","") + +# Step 1: Create user-assigned managed identity +$UserAssignedIdentity = Set-AzSKTenantSecuritySolutionScannerIdentity ` + -SubscriptionId $MIHostingSubId ` + -ResourceGroupName $MIHostingRGName ` + -Location $Location ` + -UserAssignedIdentityName $MIName ` + -TargetSubscriptionIds $TargetSubscriptionIds + +# Step 2: Save resource id and principal Id generated for user identity using below command. This will be used in AzTS Soln installation. $UserAssignedIdentity.Id +$UserAssignedIdentity.PrincipalId ``` -ii) Assign reader access to user-assigned managed identity on target subscriptions needs to be scanned. +> **NOTE:** +> 1. _For better performance, we recommend using one location of user-assigned MI and resource hosting AzTS setup._ +> +> 2. _If subscriptions are organized under [Management Groups](https://docs.microsoft.com/en-us/azure/governance/management-groups/overview) (MG), you can assign reader role for user-assigned identity using MG role assignment. You need to be 'Owner' on management group to perform role assignment._ +> +>   + +ii) The Role-based access control (RBAC) validation performed by AzTS requires privileged permission. In this step, you grant user-assigned MI read access to Privileged Identity Management APIs for Azure resources. Note that granting this permission requires admin consent. Therefore, the signed-in user must be a member of one of the following administrator roles: Global Administrator, Security Administrator, Security Reader or User Administrator. If you do not have the required permission, please contact your administrator to get "PrivilegedAccess.Read.AzureResources" permission for your scanner MI in Azure Active Directory. ``` Powershell -# Add target subscriptionds in place of -$TargetSubscriptionIds = @("","","") +# Grant Graph Permission to the user-assigned managed identity. +# Required Permission: Global Administrator, Security Administrator, Security Reader or User Administrator. -$TargetSubscriptionIds | % { -New-AzRoleAssignment -ApplicationId $UserAssignedIdentity.ClientId -Scope "/subscriptions/$_" -RoleDefinitionName "Reader" -} +Grant-AzSKGraphPermissionToUserAssignedIdentity -ScanIdentityObjectId $UserAssignedIdentity.PrincipalId -AppPermissionsRequired "PrivilegedAccess.Read.AzureResources" ``` +> **Can you proceed without this step? What is the impact?**
+Yes, you can proceed without this step. However, in this case, you will have to disable features dependent on Graph API. To disable this feature, set the value of '-ScanIdentityHasGraphPermission' parameter to false in AzTS installation command. Example: ```-ScanIdentityHasGraphPermission:$false```. +> +> On disabling this feature, RBAC controls that are evaluated based on Graph API response will be excluded from AzTS scan result. In addition to this, if a user is classic administrator on a subscription, they will not be able to view its scan result in AzTS UI. - **Note:** If subscriptions are organized under [Management Groups](https://docs.microsoft.com/en-us/azure/governance/management-groups/overview) (MG), you can assign reader role for user-assigned identity using MG role assignment. You need to be 'Owner' on target subscription to perform role assignment. -**4. Download and extract deployment package** - - Deployment packages mainly contains - ARM template: Contains resource configuration details that needs to be created as part of setup - Deployment setup script: Provides the cmdlet to run installation. +**Step 5 of 6. Setup Azure AD application for AzTS UI and API** -i) Download deployment package zip from [here](https://github.com/azsk/DevOpsKit-docs/raw/users/TenantSecurity/13-Tenant%20Security%20Solution%20Setup/TemplateFiles/Deploy.zip) to your local machine. +AzTS UI and API require Azure AD applications for authentication. Use the below PowerShell command to perform the following operations: -ii) Extract zip to local folder location + 1. Create Azure AD application for UI, if it does not exist. + 2. Create Azure AD application for API, if it does not exist. + 3. Update UI AD application redirection URL. + 4. Grant AD applications permission to request OAuth2.0 implicit flow access tokens. This is required for browser-based apps. + 5. Grant 'User.Read' permission to UI AD application. This permission is used to read logged in user's details such as name, email, and photo. -iii) Unblock the content. Below command will help to unblock files. +Optionally, you can create AD application directly from Portal using steps provided [here](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#permissions-required-for-registering-an-app) and then run the following PowerShell command to update the application. -``` PowerShell -Get-ChildItem -Path "" -Recurse | Unblock-File -``` +``` Powershell -iv) Point current path to deployment folder and load AzTS setup script -``` PowerShell -# Point current path to extracted folder location and load setup script from deploy folder +# Step 1: Setup AD application for AzTS UI and API -CD "\Deploy" +# OPTION 1: Use following command to use an existing AD application or provide a custom name for Azure AD application. +$ADApplicationDetails = Set-AzSKTenantSecurityADApplication -WebAPIAzureADAppName "" -UIAzureADAppName "" -# Load AzTS Setup script in session -. ".\AzTSSetup.ps1" -# Note: Make sure you copy '.' present at the start of line. +# OPTION 2: Use the default naming convention. +# : Add subscription id in which Azure Tenant Security Solution needs to be installed. +# : Add resource group name in which Azure Tenant Security Solution needs to be installed. +$ADApplicationDetails = Set-AzSKTenantSecurityADApplication -SubscriptionId "" -ScanHostRGName "" -``` -[Back to top…](Readme.md#contents) -**5. Run Setup Command** +# Step 2: Save WebAPIAzureADAppId and UIAzureADAppId generated for Azure AD application using below command. This will be used in AzTS Soln installation. + +$ADApplicationDetails.WebAPIAzureADAppId +$ADApplicationDetails.UIAzureADAppId + +``` + +**Step 6 of 6. Run Setup Command** This is the last step. You need to run install command present as part setup scription with host subscription id (sub where scanning infra resources will get created). -Setup will create infra resources and schedule daily security control scan on target subscriptions. +Setup will create infra resources and schedule daily security control scan on target subscriptions. Please validate you have 'Owner' access on subscrption where solution needs to be installed. **Note:** Setup may take upto 5 minutes to complete. + +i) Run installation command with required parameters. + ``` PowerShell - # Set the context to hosting subscription - Set-AzContext -SubscriptionId + # Step 1: Set the context to hosting subscription + Set-AzContext -SubscriptionId + + # Step 2: Run installation command. + + $DeploymentResult = Install-AzSKTenantSecuritySolution ` + -SubscriptionId ` + -ScanHostRGName ` + -Location ` + -ScanIdentityId ` + -WebAPIAzureADAppId ` + -UIAzureADAppId ` + -SendUsageTelemetry:$true ` + -ScanIdentityHasGraphPermission:$true ` + -SendAlertNotificationToEmailIds @('', '', '') ` + -Verbose + + # For ScanIdentityId parameter, use value created for "$UserAssignedIdentity.Id" from prerequisite section step 4 or you can get this resources id by going into Azure Portal --> Subscription where user-assigned MI resource created --> MIHostingRG --> Click on MI resource --> Properties --> Copy ResourceId. + + # For WebAPIAzureADAppId and UIAzureADAppId parameter, use value created for "$ADApplicationDetails.WebAPIAzureADAppId" and "$ADApplicationDetails.UIAzureADAppId" respectively from step 5 or you can get this application ids by going into Azure Portal --> Azure Active Directory --> App registrations --> All applications --> Search the application by name --> Click on the AD application --> Overview --> Copy Application (client) ID. + + # Example: + + $DeploymentResult = Install-AzSKTenantSecuritySolution ` + -SubscriptionId bbbe2e73-fc26-492b-9ef4-adec8560c4fe ` + -ScanHostRGName AzSK-AzTS-Solution-RG ` + -ScanIdentityId '/subscriptions/bbbe2e73-fc26-492b-9ef4-adec8560c4fe/resourceGroups/TenantReaderRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TenantReaderUserIdentity' ` + -Location EastUS2 ` + -WebAPIAzureADAppId '000000xx-00xx-00xx-00xx-0000000000xx' ` + -UIAzureADAppId '000000yy-00yy-00yy-00yy-0000000000yy' ` + -SendUsageTelemetry:$true ` + -ScanIdentityHasGraphPermission:$true ` + -SendAlertNotificationToEmailIds @('User1@Contoso.com', 'User2@Contoso.com', 'User3@Contoso.com') ` + -Verbose + +# Step 3: Save internal user-assigned managed identity name generated using below command. This will be used to grant Graph permission to internal MI. + + $InternalIdentityName = $DeploymentResult.Outputs.internalMIName.Value + + ``` + 3. Grant internal MI 'User.Read.All' permission. This permission is required by AzTS UI to read all the groups that the user is a member of.
+ **Note:** To complete this step, signed-in user must be a member of one of the following administrator roles:
+ Required Permission: Global Administrator, Security Administrator, Security Reader or User Administrator.
If you do not have the required permission, please contact your administrator. - 2. Run installation command with required parameters given. + ``` PowerShell + Grant-AzSKGraphPermissionToUserAssignedIdentity ` + -SubscriptionId "" ` + -ResourceGroupName "" ` + -IdentityName $InternalIdentityName ` + -AppPermissionsRequired @('User.Read.All') - # Step 2: Run installation command. + ``` - Install-AzSKTenantSecuritySolution ` - -SubscriptionId ` - -ScanHostRGName ` - -ScanIdentityId ` - -Location ` - -Verbose + > #### **Can you proceed without this step? What is the impact?**
+ > Yes, you can proceed without this step. + > However, please note that if this permission is not granted, users who log in to the AzTS UI will not be able to view subscriptions where they have been granted access to a subscription through a group. - # For ScanIdentityId parameter, use value created for "$UserAssignedIdentity.Id" from prerequisite section step 3 or you can get this resources id by going into Azure Portal --> Subscription where user-assigned MI resource created --> MIHostingRG --> Click on MI resource --> Properties --> Copy ResourceId. +
- # Example: +The installation is complete with this step. The following steps will walk you through the steps to validate the setup. + +
+ +> **Note:** +> +> 1. Tenant Security Solution does not support customization of app service name. +> +> 2. By default max timeout limit of function app is set to 9 minute. This can be modified based on requirement of your orgnization. To increase function timeout, you can upgrade to a higher App Service plan and use ``` AzureFunctionsJobHost__functionTimeout ``` app setting in App service to set the timeout value. - Install-AzSKTenantSecuritySolution ` - -SubscriptionId bbbe2e73-fc26-492b-9ef4-adec8560c4fe ` - -ScanHostRGName AzSK-AzTS-Solution-RG ` - -ScanIdentityId '/subscriptions/bbbe2e73-fc26-492b-9ef4-adec8560c4fe/resourceGroups/TenantReaderRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TenantReaderUserIdentity' ` - -Location EastUS2 ` - -Verbose - ``` Output looks like below ![Resources](../Images/12_TSS_CommandOutput.png) @@ -192,21 +313,35 @@ Setup will create infra resources and schedule daily security control scan on ta |ScanHostRGName| Name of ResourceGroup where setup resources will be created |TRUE| |ScanIdentityId| Resource id of user managed identity used to scan subscriptions |TRUE| |Location|Location where all resources will get created |TRUE| +|WebAPIAzureADAppId| Application (client) id of the Azure AD application to be used by the API. | TRUE | +| UIAzureADAppId | Application (client) id of the Azure AD application to be used by the UI. | TRUE| +| SendAlertNotificationToEmailIds| Send monitoring alerts notification to the specified email ids. | TRUE | +|ScanIdentityHasGraphPermission|Switch to enable features dependent on Microsoft Graph API from the scan. Set this to false if user-assigned managed identity does not have Graph permission. Default value is false.|FALSE| +|SendUsageTelemetry| Permit application to send usage telemetry to Microsoft server. Usage telemetry captures anonymous usage data and sends it to Microsoft servers. This will help in improving the product quality and prioritize meaning fully on the highly used features. Default value is false.|FALSE| |Verbose| Switch used to output detailed log |FALSE| +
+ +[Back to top…](Readme.md#contents) +
-## Verifying that Tenant Security Solution installation is complete -Below steps will help you to verify and understand different resources and functions created as part of setup along with purpose. -**1: Verify resources created as part of setup** + ![ProgressBar](../Images/12_TSS_ProgressBar2.png) + +## 2. Verifying that Tenant Security Solution installation is complete + +Below steps will help you to verify and understand different resources and functions created as part of setup along with purpose. This step can take up to 30 minutes. + +**Step 1 of 3: Verify resources created as part of setup** i) In the Azure portal, Go to hosting subscription, select the scan host resource group that has been created during the setup. -**2:** Verify below resources got created. +ii) Verify below resources got created. -![Resources](../Images/12_TSS_Resource_Group.png) + ![Resources](../Images/12_TSS_Resource_Group_1.png) + ![Resources](../Images/12_TSS_Resource_Group_2.png) **Resources details:** @@ -214,24 +349,31 @@ i) In the Azure portal, Go to hosting subscription, select the scan host resourc |----|----|----| |AzSK-AzTS-MetadataAggregator-xxxxx|Function App| Contains functions to get inventory (subscription, baseline controls and RBAC) and queue subscription for scan | |AzSK-AzTS-WorkItemProcessor-xxxxx|Function App | Contains function to scan subscription with baseline control | +|AzSK-AzTS-WebApi-xxxxx|App Service| Contains API consumed by the AzTS user interface | +|AzSK-AzTS-WebApp-xxxxx|App Service| Contains AzTS user interface which can used to view the scan result | +|AzSK-AzTS-WebApp-xxxxx/Staging-xxxxx| App service slot| Staging slot created to prevent UI downtime during auto-update| |AzSK-AzTS-AutoUpdater-xxxxx|Function App | Contains function to scan automatically updater function apps and web service apps | |AzSK-AzTS-LAWorkspace-xxxxx|Log Analytics workspace| Used to store scan events, inventory, subscription scan progress details| |AzSK-AzTS-InternalMI|Managed Identity | Internal MI identity used to access LA workspace and storage for sending scan results| -|AzSK-AzTS-AppServicePlan | Function App Service Plan| Function app service plan| +|AzSK-AzTS-AppServicePlan | Web App Service Plan| Web app service plan| +|AzSK-AzTS-API-AppServicePlan | Function App Service Plan| Function app service plan| |azsktsstoragexxxxx|Storage Account| Used to store the daily results of subscriptions scan| |AzSK-AzTS-AppInsights |App Insight| Used to collect telemetry logs from functions | - **3:** Verify below Functions got created +
+ + **Step 2 of 3: Verify below Functions got created** - **i) MetadataAggregator Functions:** +**i) MetadataAggregator Functions:** -Metadata aggregator function performs two tasks: +   Metadata aggregator function performs two tasks: 1. Collects inventory required for scanning (Target subscription list to be scanned, baseline controls list and subscription RBAC details) 2. Queue subscriptions for scanning +
-Click on 'AzSK-AzTS-MetadataAggregator-xxxxx' function app present in scan hosting RG --> Click on 'Functions' tab in left menu +   Click on 'AzSK-AzTS-MetadataAggregator-xxxxx' function app present in scan hosting RG --> Click on 'Functions' tab in left menu -![ProcessorWebjobs](../Images/12_TSS_Processor_WebJobs.png) +    ![ProcessorWebjobs](../Images/12_TSS_Processor_WebJobs_1.png) |Function Name|Description| |----|----| @@ -239,6 +381,7 @@ Click on 'AzSK-AzTS-MetadataAggregator-xxxxx' function app present in scan hosti |ATS_2_BaselineControlsInvProcessor| Responsible to push baseline controls metadata to LA and storage account |ATS_3_SubscriptionRBACProcessor| Collects RBAC details of subscription to be scanned. RBAC collected used to scan the control like "Azure_Subscription_AuthZ_Dont_Use_NonAD_Identities" |ATS_4_WorkItemScheduler| Responsible to queue up subscriptions as workitems for scanning. It also reconciles the errored subscriptions through retries in the end. By default it would retry to scan for 5 times for each error subscription. IF there is nothing to process for the day, it would simply ignore the run. +|ATS_5_MGTreeProcessor| Responsible to fetch details about all the management group that has been granted access as Reader using central MI. All these management group will be fetched by the job and persisted into LA. This function is disabled by default. To enable this function, you need to add ``` FeatureManagement__ManagementGroups : true ``` and ``` ManagementGroupConfigurations__ManagementGroupId : ``` to the Application settings on Azure Portal. To update application settings in the app service, go to Configuration --> New application settings --> Save after adding/updating the setting. **ii) WorkItemProcessor Functions:** @@ -265,9 +408,9 @@ After ATS_4_WorkItemScheduler completes pushing the messages in the queue, WorkI **iii) AutoUpdater Functions:** - Timer based function app to automatically update other function apps(Metadataaggregator and WorkItemProcessor) and azure web service app(UI and API). User has the option to configure AutoUpdater settings like isAutoUpdateOn(user wants to auto update with new releases), VersionType(user wants to install the latest release/stable release/specific version). + Timer based function app to automatically update other function apps (Metadataaggregator and WorkItemProcessor) and azure web service app(UI and API). User has the option to configure AutoUpdater settings like isAutoUpdateOn (user wants to auto update with new releases), VersionType (user wants to install the latest release/stable release/specific version). - AutoUpdater is a cron job which runs every 5 hrs automatically to check for new release to update the apps. You can also manually trigger the AutoUpdater function if needed. + AutoUpdater is a cron job which runs twice a day at 02:00 PM and 04:00 PM (UTC) to check for new release to update the apps. You can also manually trigger the AutoUpdater function if needed. Our AutoUpdater is robust enough to handle different configuration for each function apps or web service apps. > **Note:** If you want to install specific version for each different apps(or a specific version for all) follow the below steps, @@ -275,7 +418,125 @@ After ATS_4_WorkItemScheduler completes pushing the messages in the queue, WorkI (ii) Manually trigger the AutoUpdate function app. You can view the console/monitor logs to see appropriate status of AutoUpdater function. (iii) After AutoUpdater function execution gets complete, you need to change **isAutoUpdateOn** to **false** through the app configuration setting for the apps where you want to keep custom version installed. -## Log Analytics Visualization +
+ +[Back to top…](Readme.md#contents) + +**Steps 3 of 3: Verify AzTS UI is working as expected** + +**Prerequisite:** + +1. Signed in user must have one of the following permission at subscription or resource group scope: Owner, Contributor, ServiceAdministrator, CoAdministrator, AccountAdministrator, Security Reader, Security Admin. +2. Subscription scan should have completed for the day. The steps to validate this has been specified under [this section](Readme.md#2-verifying-that-tenant-security-solution-installation-is-complete). + +**Steps to load AzTS UI** + + **a)** Validate that the scan has completed. For validation, Go to AzSK-AzTS-LAWorkspace-xxxxx Log Analytics workspace --> Logs --> Run the following queries. If the queries listed below returns a response, AzTS UI is ready to be loaded. + + i) List subscription(s) that user-managed identity has access to. + ```kql + AzSK_SubInventory_CL + | distinct SubscriptionId, Name_s + ``` + + ii) List controls supported by Tenant Security solution. + ```kql + AzSK_BaselineControlsInv_CL + | distinct ControlId_s, DisplayName_s + ``` + iii) List role-based access control (RBAC) inventory. + ```kql + AzSK_RBAC_CL + ``` + + iv) List control scan result. + ```kql + AzSK_ControlResults_CL + ``` + + **b)** Go to link provided at the end of installation command ```Install-AzSKTenantSecuritySolution``` (as shown below). +  ![UI](../Images/13_TSS_UIUrlPrintMessageInPSOutput.png) + +[Back to top…](Readme.md#contents) + + +# 3. Visualization + + ![ProgressBar](../Images/12_TSS_ProgressBar3.png) + +## 1. AzTS UI + +Tenant reader solution provides a UI-based tool that can be used to perform on-demand scans to verify your fixes sooner, check reasons for control failures and view latest scan results. This tool leverages you current subscription permissions to show you subscriptions that you have the ability to request scans for. + +**Prerequisite:** + +1. Signed in user must have one of the following permission at subscription or resource group scope: Owner, Contributor, ServiceAdministrator, CoAdministrator, AccountAdministrator, Security Reader, Security Admin. +2. Subscription scan should have completed for the day. The steps to validate this has been specified under [this section](Readme.md#2-verifying-that-tenant-security-solution-installation-is-complete). + +Link to the AzTS UI is provided at the end of installation command ```Install-AzSKTenantSecuritySolution``` (as shown below). +  ![UI](../Images/13_TSS_UIUrlPrintMessageInPSOutput.png) + +The UI is fairly self-explanatory and also has a "Guided Tour" feature that should show you the basic usage workflow. We recommend that you create a custom domain name for your UI. For steps to create custom domain, refer this [link](https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-custom-domain). + +  ![UI](../Images/13_TSS_UIOverview.png) + +TODO: Add UI walk through video. + +> **Note:** +> 1. If you have been recently granted access, you either need to wait for the next scheduled scan to read the latest RBAC data or request an existing owner of a subscription to perform an ad hoc scan for the subscription using AzTS UI. +> +>
+ +
+ +**Add org-subscription mapping for your subscription(s)**: + +By default, there is no service mapping for your subscription. Therefore, you see the 'Unknown' value is the Service Filter dropdown. To add service mapping, follow the steps below: + +#### Step 1 of 2: Prepare your org-subscription mapping +In this step you will prepare the data file with the mapping from subscription ids to the org hierarchy within your environment. The file is in a simple CSV form and should appear like the one below. + +> Note: You may want to create a small CSV file with just a few subscriptions for a trial pass and then update it with the full subscription list for your org after getting everything working end-to-end. + +A sample template for the CSV file is [here](TemplateFiles/OrgMapping.csv): + +![Org-Sub metadata json](../Images/13_TSS_OrgMappingCSV.png) + +The table below describes the different columns in the CSV file and their intent. + +| ColumnName | Description | Required? |Comments| +| ---- | ---- | ---- | ---- | +| OrganizationName | Name of Organization(s) within your enterprise | No | This you can consider as level 1 hierarchy for your enterprise | +| DivisionName | Name of Division(s) within your organization | No | This you can consider as level 2 hierarchy for your enterprise | +| ServiceGroupName | Name of Service Line/ Business Unit within an organization | No | This you can consider as level 3 hierarchy for your enterprise | +| TeamGroupName | Name of Team(s) within an organization | No | This you can consider as level 4 hierarchy for your enterprise | +| ServiceName | Name of Service(s) within your organization | No | This you can consider as level 5 hierarchy for your enterprise | +| SubscriptionId | Subscription Id belonging to a org/servicegroup | Yes | +| SubscriptionName | Subscription Name | Yes | + +
+ +> **Note**: Ensure you follow the correct casing for all column names as shown in the table above. + +
+ +#### Step 2 of 2: Upload your mapping to the Log Analytics (LA) workspace + +In this step you will import the data above into the LA workspace created during Tenant Security setup. + + **(a)** Locate the LA resource that was created during Tenant Security setup in your subscription. This should be present under Tenant Security resource group. After selecting the LA resource, copy the Workspace ID and primary key from the portal as shown below: + + ![capture Workspace ID](../Images/13_TSS_LAWS_AgentManagement.png) + + **(b)** To push org Mapping details, copy and execute the script available [here](Scripts/AzTSPushOrgMappingEvents.ps1) (for Gov subs use script [here](Scripts/AzTSPushOrgMappingEvents.Gov.ps1)) in Powershell. You will need to replace the CSV path, Workspace ID, and primary key with its approriate value in this PowerShell script. + +
+ + > **Note**: Due to limitation of Log Analytics workspace, you will need to repeat this step every 90 days interval. + +
+ +## 2. Log Analytics Visualization For understanding the collected data, use the querying and visualization capabilities provided by Log Analytics. To start, go to **Log Analytics workspace** created during setup --> Select **Logs**. @@ -355,8 +616,8 @@ AzSK_ControlResults_CL | take 10 ``` - [Back to top…](Readme.md#contents) + ## Tenant Security Solution - under the covers (how it works) Tenant Security Solution is built by extending what the DevOps Kit has been doing and leveraging the best of Azure native features. It is a hybrid model, which leverages the native Azure security capabilities like Azure Security Center (ASC), Azure Policies, etc., to evaluate the security controls and continue to leverage DevOps Kit scanning capabilities in the form of custom code controls to address any coverage gaps. @@ -389,20 +650,23 @@ In this step you will prepare the data file which will be fed to the PowerBI das > Note: You may want to create a small CSV file with just a few subscriptions for a trial pass and then update it with the full subscription list for your org after getting everything working end-to-end. -A sample template for the CSV file is [here](https://raw.githubusercontent.com/azsk/DevOpsKit-docs/users/TenantSecurity/13-Tenant%20Security%20Solution%20Setup/TemplateFiles/OrgMapping.csv): +A sample template for the CSV file is [here](TemplateFiles/OrgMapping.csv): -![Org-Sub metadata json](../Images/07_OrgPolicy_PBI_OrgMetadata.PNG) +![Org-Sub metadata json](../Images/13_TSS_OrgMappingCSV.png) The table below describes the different columns in the CSV file and their intent. -| ColumnName | Description | Required? | Comments | -| ---- | ---- | ---- |---- | -| BGName | Name of business group (e.g., Finance, HR, Marketing, etc.) within your enterprise | Yes | This you can consider as level 1 hierarchy for your enterprise | -| ServiceGroupName | Name of Service Line/ Business Unit within an organization | Yes | This you can consider as level 2 hierarchy for your enterprise | -| SubscriptionId | Subscription Id belonging to a org/servicegroup | Yes | | -| SubscriptionName | Subscription Name | Yes | This should match the actual subscription name. If it does not, then the actual name will be used | -| IsActive | Use "Y" for Active Subscription and "N" for Inactive Subscription | Yes | This will be used to filter active and inactive subscriptions | -| OwnerDetails | List of subscription owners separated by semi-colons (;) | Yes | These are people accountable for security of the subscription | +| ColumnName | Description | Required? |Comments| +| ---- | ---- | ---- | ---- | +| OrganizationName | Name of Organization(s) within your enterprise | No | This you can consider as level 1 hierarchy for your enterprise | +| DivisionName | Name of Division(s) within your organization | No | This you can consider as level 2 hierarchy for your enterprise | +| ServiceGroupName | Name of Service Line/ Business Unit within an organization | No | This you can consider as level 3 hierarchy for your enterprise | +| TeamGroupName | Name of Team(s) within an organization | No | This you can consider as level 4 hierarchy for your enterprise | +| ServiceName | Name of Service(s) within your organization | No | This you can consider as level 5 hierarchy for your enterprise | +| SubscriptionId | Subscription Id belonging to a org/servicegroup | Yes | +| SubscriptionName | Subscription Name | Yes | + +
> **Note**: Ensure you follow the correct casing for all column names as shown in the table above. The 'out-of-box' PowerBI template is bound to these columns. If you need additional columns to represent your org hierarchy then you may need to modify the template/report as well. @@ -411,11 +675,11 @@ The table below describes the different columns in the CSV file and their intent In this step you will import the data above into the LA workspace created during Tenant Security setup. - **(a)** Locate the LA resource that was created during Tenant Security setup in your subscription. This should be present under Tenant Security resource group. After selecting the LA resource, copy the Workspace ID from the portal as shown below: + **(a)** Locate the LA resource that was created during Tenant Security setup in your subscription. This should be present under Tenant Security resource group. After selecting the LA resource, copy the Workspace ID and primary key from the portal as shown below: ![capture Workspace ID](../Images/13_TSS_LAWS_AgentManagement.png) - **(b)** To push org Mapping details, copy and execute the script available [here](https://raw.githubusercontent.com/azsk/DevOpsKit-docs/master/13-Tenant%20Security%20Solution%20Setup/Scripts/AzTSPushOrgMappingEvents.ps1) (for Gov subs use script [here](https://raw.githubusercontent.com/azsk/DevOpsKit-docs/master/13-Tenant%20Security%20Solution%20Setup/Scripts/AzTSPushOrgMappingEvents.Gov.ps1)) in Powershell. + **(b)** To push org Mapping details, copy and execute the script available [here](Scripts/AzTSPushOrgMappingEvents.ps1) (for Gov subs use script [here](Scripts/AzTSPushOrgMappingEvents.Gov.ps1)) in Powershell. You will need to replace the CSV path, Workspace ID, and primary key with its approriate value in this PowerShell script. > **Note**: Due to limitation of Log Analytics workspace, you will need to repeat this step every 90 days interval. diff --git a/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.Gov.ps1 b/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.Gov.ps1 index 19db424e..43d424ac 100644 --- a/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.Gov.ps1 +++ b/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.Gov.ps1 @@ -57,7 +57,15 @@ function PushOrgMappingEvents([string] $OrgMappingFilePath, [string] $LogAnaytic $body = Get-Content $FilePath | ConvertFrom-Csv $body | ForEach-Object { - $OrgMappingList+= @{ "BGName" = $_.BGName; "ServiceGroupName" = $_.ServiceGroupName; "SubscriptionId" =$_.SubscriptionId; "SubscriptionName" = $_.SubscriptionName; "IsActive" = $_.IsActive; "OwnerDetails" = $_.OwnerDetails } + $OrgMappingList+= @{ + "OrganizationName" = $_.OrganizationName ; + "DivisionName" = $_.DivisionName ; + "ServiceGroupName" = $_.ServiceGroupName ; + "TeamGroupName" = $_.TeamGroupName ; + "ServiceName" = $_.ServiceName ; + "SubscriptionId" = $_.SubscriptionId ; + "SubscriptionName" = $_.SubscriptionName ; + } } $postbody = $OrgMappingList | ConvertTo-Json $lawsBodyByteArray = ([System.Text.Encoding]::UTF8.GetBytes($postbody)) diff --git a/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.ps1 b/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.ps1 index 4632c017..cd1568a8 100644 --- a/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.ps1 +++ b/13-Tenant Security Solution Setup/Scripts/AzTSPushOrgMappingEvents.ps1 @@ -57,7 +57,15 @@ function PushOrgMappingEvents([string] $OrgMappingFilePath, [string] $LogAnaytic $body = Get-Content $FilePath | ConvertFrom-Csv $body | ForEach-Object { - $OrgMappingList+= @{ "BGName" = $_.BGName; "ServiceGroupName" = $_.ServiceGroupName; "SubscriptionId" =$_.SubscriptionId; "SubscriptionName" = $_.SubscriptionName; "IsActive" = $_.IsActive; "OwnerDetails" = $_.OwnerDetails } + $OrgMappingList+= @{ + "OrganizationName" = $_.OrganizationName ; + "DivisionName" = $_.DivisionName ; + "ServiceGroupName" = $_.ServiceGroupName ; + "TeamGroupName" = $_.TeamGroupName ; + "ServiceName" = $_.ServiceName ; + "SubscriptionId" = $_.SubscriptionId ; + "SubscriptionName" = $_.SubscriptionName ; + } } $postbody = $OrgMappingList | ConvertTo-Json $lawsBodyByteArray = ([System.Text.Encoding]::UTF8.GetBytes($postbody)) diff --git a/13-Tenant Security Solution Setup/Scripts/ExecutionScript.ps1 b/13-Tenant Security Solution Setup/Scripts/ExecutionScript.ps1 index 6d4f16e7..26df87fe 100644 --- a/13-Tenant Security Solution Setup/Scripts/ExecutionScript.ps1 +++ b/13-Tenant Security Solution Setup/Scripts/ExecutionScript.ps1 @@ -1,56 +1,20 @@  #****************** Prerequisite ***************** -# *** 1. Validate prerequisites on machine +# *** 1 of 6. Validate prerequisites on machine #Ensure that you are using Windows OS and have PowerShell version 5.0 or higher $PSVersionTable -# *** 2. Installing Az Modules +# *** 2 of 6. Installing Az Modules # Install Az Modules Install-Module -Name Az.Accounts -AllowClobber -Scope CurrentUser -repository PSGallery Install-Module -Name Az.Resources -AllowClobber -Scope CurrentUser -repository PSGallery Install-Module -Name Az.Storage -AllowClobber -Scope CurrentUser -repository PSGallery Install-Module -Name Az.ManagedServiceIdentity -AllowClobber -Scope CurrentUser -repository PSGallery + Install-Module -Name Az.Monitor -AllowClobber -Scope CurrentUser -repository PSGallery -# *** 3. Setting up scanning identity - #Before creating user-assigned managed identity, please connect to AzureAD and AzAccount with the tenant Id where you want to use AzTS solution. - Connect-AzAccount -Tenant - Connect-AzureAD -TenantId - - # i) You can create user-assigned managed identity with below PowerShell command - # Step 1: Set context to subscription where user-assigned managed identity needs to be created - Set-AzContext -SubscriptionId "" - - # Step 2: Create resource group where user-assigned MI resource will be created. - New-AzResourceGroup -Name "" -Location "" - - # Step 3: Create user-assigned managed identity - $UserAssignedIdentity = New-AzUserAssignedIdentity -ResourceGroupName "" -Name "" - - # Step 4: Save resource id generated for user identity using below command. This will be used in AzTS Soln installation. - - $UserAssignedIdentity.Id - - # ii) Assign reader access to user-assigned managed identity on target subscriptions to be scanned. - - # Add target subscriptionds in place of - $TargetSubscriptionIds = @("","","") - - $TargetSubscriptionIds | % { - New-AzRoleAssignment -ApplicationId $UserAssignedIdentity.ClientId -Scope "/subscriptions/$_" -RoleDefinitionName "Reader" - } - - -# *** 3. Set context and validate you have 'Owner' access on subscrption where solution needs to be installed **** - - # Set the context to hosting subscription - $HostSubscriptionId = "" - - Set-AzContext -SubscriptionId $HostSubscriptionId - - -# **** 4. Download and extract deployment template +# **** 3 of 6. Download and extract deployment template # i) Download deployment package zip from link (https://aka.ms/DevOpsKit/AzTS/DeploymentTemplate) to your local machine. @@ -74,20 +38,128 @@ . ".\AzTSSetup.ps1" +# *** 4 of 6. Setting up scanning identity + #Before creating user-assigned managed identity, please connect to AzureAD and AzAccount with the tenant Id where you want to use AzTS solution. + + # Clear existing login, if any + Disconnect-AzAccount + Disconnect-AzureAD -# **** 5. Run Setup Command - # Set the context to hosting subscription - Set-AzContext -SubscriptionId "" - + # Connect to AzureAD and AzAccount + Connect-AzAccount -Tenant + Connect-AzureAD -TenantId - # Provide resource group name where resources will be created - $ScanHostRGName = "" #RG name where - $Location = "" # eg. EastUS2 + # i) You can create user-assigned managed identity (MI) with below PowerShell command + + # Subscription id in which scanner MI needs to be created. + $MIHostingSubId = "" + + # Resource group name in which scanner MI needs to be created. + $MIHostingRGName = "" + + # Location in which scanner MI needs to be created. + # Note: For better performance, we recommend hosting the MI and resources setup using AzTS Soln installation command in one location. + $Location = "" + + # Name of the scanner MI. + $MIName = "" + + # List of target subscription(s) that needs to be scanned by AzTS. + # This command assigns 'Reader' access to user-assigned managed identity on target subscriptions. Add target subscriptionds in place of + $TargetSubscriptionIds = @("","","") + + # Step 1: Create user-assigned managed identity + $UserAssignedIdentity = Set-AzSKTenantSecuritySolutionScannerIdentity -SubscriptionId $MIHostingSubId ` + -ResourceGroupName $MIHostingRGName ` + -Location $Location ` + -UserAssignedIdentityName $MIName ` + -TargetSubscriptionIds $TargetSubscriptionIds + + # Step 2: Save resource id and principal Id generated for user identity using below command. This will be used in AzTS Soln installation. + + $UserAssignedIdentity.Id + $UserAssignedIdentity.PrincipalId + + # ii) Grant user-assigned managed identity read access to Privileged Identity Management APIs for Azure resources. + + # Grant Graph Permission to the user-assigned managed identity. + # NOTE: This step requires admin consent. Therefore, the signed-in user must be a member of one of the following administrator roles: + # Required Permission: Global Administrator, Privileged Role Administrator, Application Administrator or Cloud Application Administrator. + Grant-AzSKGraphPermissionToUserAssignedIdentity -ScanIdentityObjectId $UserAssignedIdentity.PrincipalId -AppPermissionsRequired @("PrivilegedAccess.Read.AzureResources", "Directory.Read.All") + + # If you do not have the permission required to complete this step, please contact your administrator. + # To proceed without this step, set the value of "-ScanIdentityHasGraphPermission" parameter to false in AzTS installation command. Example: -ScanIdentityHasGraphPermission:$false. + # By setting '-ScanIdentityHasGraphPermission' to $false, you are choosing to disable features dependent on Graph API. + # Read more about this under the section "Step 4 of 6. Setting up scanning identity" in GitHub doc. + +# *** 5 of 6. Setup Azure AD application for AzTS UI and API + + # Step 1: Setup AD application for AzTS UI and API + + # OPTION 1: Use following command to use an existing AD application or provide a custom name for Azure AD application. + # Name of the Azure AD application to be used by AzTS API + $WebAPIAzureADAppName = "" + + # Name of the Azure AD application to be used by AzTS UI + $UIAzureADAppName = "" + + $ADApplicationDetails = Set-AzSKTenantSecurityADApplication -WebAPIAzureADAppName $WebAPIAzureADAppName -UIAzureADAppName $UIAzureADAppName + + + # OPTION 2: Use the default naming convention. + # Subscription id in which Azure Tenant Security Solution needs to be installed. + $HostSubscriptionId = "" + + # Resource group name in which Azure Tenant Security Solution needs to be installed. + $HostResourceGroupName = "" + + $ADApplicationDetails = Set-AzSKTenantSecurityADApplication -SubscriptionId $HostSubscriptionId -ScanHostRGName $HostResourceGroupName + + # Step 2: Save WebAPIAzureADAppId and UIAzureADAppId generated for Azure AD application using below command. This will be used in AzTS Soln installation. + + $ADApplicationDetails.WebAPIAzureADAppId + $ADApplicationDetails.UIAzureADAppId + + +# *** 6 of 6. Set context and validate you have 'Owner' access on subscrption where solution needs to be installed **** + + # Run Setup Command + # i) Set the context to hosting subscription + $HostSubscriptionId = "" + + Set-AzContext -SubscriptionId $HostSubscriptionId + + # Provide resource group name where resources will be created + $ScanHostRGName = "" #RG name where solution needs to be installed + $Location = "" # eg. EastUS2 + $EmailIds = @('', '', '') # Comma-separated list of user email ids who should be sent the monitoring email. + + # ii) Run install solution command + $DeploymentResult = Install-AzSKTenantSecuritySolution ` + -SubscriptionId $HostSubscriptionId ` + -ScanHostRGName $ScanHostRGName ` + -ScanIdentityId $UserAssignedIdentity.Id ` + -Location $Location ` + -WebAPIAzureADAppId $ADApplicationDetails.WebAPIAzureADAppId ` + -UIAzureADAppId $ADApplicationDetails.UIAzureADAppId ` + -SendUsageTelemetry:$true ` + -ScanIdentityHasGraphPermission:$false ` + -SendAlertNotificationToEmailIds $EmailIds ` + -Verbose + + # iii) Save internal user-assigned managed identity name generated using below command. This will be used to grant Graph permission to internal MI. + $InternalIdentityName = $DeploymentResult.Outputs.internalMIName.Value + + # iv) Grant internal MI 'User.Read.All' permission. + + # **Note:** To complete this step, signed-in user must be a member of one of the following administrator roles:
+ # Required Permission: Global Administrator, Privileged Role Administrator, Application Administrator or Cloud Application Administrator. + # If you do not have the required permission, please contact your administrator. + # Read more about this under the section "Step 6 of 6. Run Setup Command" in GitHub doc. + + Grant-AzSKGraphPermissionToUserAssignedIdentity ` + -SubscriptionId $HostSubscriptionId ` + -ResourceGroupName $ScanHostRGName ` + -IdentityName $InternalIdentityName ` + -AppPermissionsRequired @('User.Read.All') - # Run install solution command - Install-AzSKTenantSecuritySolution ` - -SubscriptionId $HostSubscriptionId ` - -ScanHostRGName $ScanHostRGName ` - -ScanIdentityId $UserAssignedIdentity.Id ` - -Location $Location ` - -Verbose diff --git a/13-Tenant Security Solution Setup/TemplateFiles/Deploy.zip b/13-Tenant Security Solution Setup/TemplateFiles/Deploy.zip deleted file mode 100644 index 834db5f4..00000000 Binary files a/13-Tenant Security Solution Setup/TemplateFiles/Deploy.zip and /dev/null differ diff --git a/13-Tenant Security Solution Setup/TemplateFiles/DeploymentFiles.zip b/13-Tenant Security Solution Setup/TemplateFiles/DeploymentFiles.zip new file mode 100644 index 00000000..31951660 Binary files /dev/null and b/13-Tenant Security Solution Setup/TemplateFiles/DeploymentFiles.zip differ diff --git a/13-Tenant Security Solution Setup/TemplateFiles/OrgMapping.csv b/13-Tenant Security Solution Setup/TemplateFiles/OrgMapping.csv index 55b16491..4d23016b 100644 --- a/13-Tenant Security Solution Setup/TemplateFiles/OrgMapping.csv +++ b/13-Tenant Security Solution Setup/TemplateFiles/OrgMapping.csv @@ -1,2 +1,3 @@ -BGName,ServiceGroupName,SubscriptionId,SubscriptionName,IsActive,OwnerDetails -BGName1,Sg1,SubId1,SubName1,Y,Owner@Contoso.com;Owner1@Contoso.com +OrganizationName,DivisionName,ServiceGroupName,TeamGroupName,ServiceName,SubscriptionId,SubscriptionName +OrgName1,DivisionName1,ServiceGroupName1,TeamGroupName1,ServiceName1,SubscriptionId1,SubscriptionName1 +OrgName2,DivisionName2,ServiceGroupName2,TeamGroupName2,ServiceName2,SubscriptionId2,SubscriptionName2 diff --git a/13-Tenant Security Solution Setup/TemplateFiles/TenantSecurityReport.pbit b/13-Tenant Security Solution Setup/TemplateFiles/TenantSecurityReport.pbit index 289fdead..6b8b8c3f 100644 Binary files a/13-Tenant Security Solution Setup/TemplateFiles/TenantSecurityReport.pbit and b/13-Tenant Security Solution Setup/TemplateFiles/TenantSecurityReport.pbit differ diff --git a/Images/12_TSS_Processor_WebJobs_1.png b/Images/12_TSS_Processor_WebJobs_1.png new file mode 100644 index 00000000..55bc1fca Binary files /dev/null and b/Images/12_TSS_Processor_WebJobs_1.png differ diff --git a/Images/12_TSS_ProgressBar1.png b/Images/12_TSS_ProgressBar1.png new file mode 100644 index 00000000..59744181 Binary files /dev/null and b/Images/12_TSS_ProgressBar1.png differ diff --git a/Images/12_TSS_ProgressBar2.png b/Images/12_TSS_ProgressBar2.png new file mode 100644 index 00000000..40db57db Binary files /dev/null and b/Images/12_TSS_ProgressBar2.png differ diff --git a/Images/12_TSS_ProgressBar3.png b/Images/12_TSS_ProgressBar3.png new file mode 100644 index 00000000..a61c888c Binary files /dev/null and b/Images/12_TSS_ProgressBar3.png differ diff --git a/Images/12_TSS_Resource_Group_1.png b/Images/12_TSS_Resource_Group_1.png new file mode 100644 index 00000000..a17e0fa8 Binary files /dev/null and b/Images/12_TSS_Resource_Group_1.png differ diff --git a/Images/12_TSS_Resource_Group_2.png b/Images/12_TSS_Resource_Group_2.png new file mode 100644 index 00000000..5e1eec91 Binary files /dev/null and b/Images/12_TSS_Resource_Group_2.png differ diff --git a/Images/13_TSS_OrgMappingCSV.png b/Images/13_TSS_OrgMappingCSV.png new file mode 100644 index 00000000..1d9fd17e Binary files /dev/null and b/Images/13_TSS_OrgMappingCSV.png differ diff --git a/Images/13_TSS_UIOverview.png b/Images/13_TSS_UIOverview.png new file mode 100644 index 00000000..e4ca8609 Binary files /dev/null and b/Images/13_TSS_UIOverview.png differ diff --git a/Images/13_TSS_UIUrlPrintMessageInPSOutput.png b/Images/13_TSS_UIUrlPrintMessageInPSOutput.png new file mode 100644 index 00000000..ba4ed434 Binary files /dev/null and b/Images/13_TSS_UIUrlPrintMessageInPSOutput.png differ