diff --git a/00a-Setup/AzSK.zip b/00a-Setup/AzSK.zip new file mode 100644 index 00000000..f99d868d Binary files /dev/null and b/00a-Setup/AzSK.zip differ diff --git a/00a-Setup/Migration.md b/00a-Setup/Migration.md deleted file mode 100644 index 03a14f2e..00000000 --- a/00a-Setup/Migration.md +++ /dev/null @@ -1,110 +0,0 @@ -## Migrating from 'AzSDK' to 'AzSK' - -

IMPORTANT:

- -> 1) If you are from Microsoft CSE, please use the steps [here](https://aka.ms/devopskit/migration). -> **Do not** use the migration instructions on this page. ->> -> 2) If you are external to Microsoft **and** you have setup your own org-policy server for AzSDK (using -> `Install-AzSDKOrganizationPolicy` as covered [here](https://github.com/azsdk/azsdk-docs/tree/master/07-Customizing-AzSDK-for-your-Org)), -please **do not** migrate your subscription(s) yet. Support for migrating org-policy based setups will be in the next sprint release. -(Please watch this page for updates.) -> -> 3) The steps below are only for orgs external to Microsoft CSE that have *not* setup their own org policy. - -### Migration Steps: -The DevOps Kit PS module has been renamed from 'AzSDK' to 'AzSK'. (See 'FAQ' below for details.) - -If you have been using the DevOps Kit for your subscriptions, you can switch to the new module by following -the steps below to migrate your subscription: - -(Pre-requisite: You should be an **Owner** for the subscription being migrated.) - - 0) Close all PS sessions. - - 1) Open a *fresh* PS session and install the latest release by running the command below (this will get - the new 'AzSK' module onto your machine): - - ```PowerShell - install-module AzSK -Scope CurrentUser - ``` - - - 2) Close the installation session, open a *fresh* PS session and run the following: - - ```PowerShell - import-module AzSK - Update-AzSKSubscriptionSecurity -SubscriptionId -Migrate - ``` - - -This will make all changes necessary in your subscription in order to start using the new ('AzSK') module. -If any of the individual steps fail, you can retry migration by just re-running the 'migrate' command -(per Step-2 above). If that does not resolve it, please post a support query. - -For other questions related to migration (e.g., *Why are we migrating? What happens behind the scenes during -migration? What about CICD?* etc., please see the FAQ at the end of this page. - -**Note:** Until a subscription is migrated, you may be able to use the 'AzSDK' module and corresponding 'AzSDK' -versions of cmdlets by installing the latest AzSDK module using `install-module AzSDK -Scope CurrentUser -AllowClobber` as always. -However, after a subscription has been migrated, new 'AzSK' versions of the cmdlets -in the new module should be used. The logs generated by local scan commands from the new module will appear -under the `'%localappdata%\Microsoft\AzSKLogs'` folder - - -#### FAQ: - -##### Why are we migrating from AzSDK to AzSK? -We received feedback from various forums that the 'SDK' in the module name was misleading because 'SDK' is -traditionally used for 'Software Development Kit'. Secondly, some folks were also confusing 'AzSDK' and 'Azure SDK' -using the two interchangeably. - - -##### What exactly happens during migration? -The migration process basically prepares your local machine and your subscription to start using the new -'AzSK' PS module. Depending on the subscription security features from the DevOps Kit you have setup on your -subscription, the following steps happen during migration: - - - The old resource group ('AzSDKRG') will be retained for certain duration and locked for any modifications post migration - - Attestation data/ Resource groups tags are auto migrated to the new resource group ('AzSKRG') - - Attestation data is still retained in the old storage account as backup - - Previously setup alerts, ARM policies and Continuous Assurance Automation Account will get deleted - and corresponding new resources will get created under AzSK RG. - -If you created any other resources under the (old) DevOps Kit resource group ('AzSDKRG') you may need to migrate -them yourselves. - -##### How will the old cmdlets (from the old 'AzSDK' module) behave? -If you have not yet migrated, all AzSDK cmdlets (Get-AzSDKxxx or Set-AzSDKxxx) will work as usual. The latest -version of AzSDK (2.11.x) will show warnings about migration. - -Once you migrate your subscription, most cmdlets from AzSDK 2.11.x will report errors telling you to use -cmdlets from the 'AzSK' module. - -##### Can I use the new 'AzSK' module if I have not migrated? -Some commands (which are 'read only' in behavior) will work. However, others (e.g., attestation or Set-AzSKSubscriptionSecurity) -will be blocked. This is to not create conflicts with 'AzSDK-based' state in the subscription. - -##### How will Continuous Assurance transition through migration? -If you have not yet migrated, the current AzSDK setup will seamlessly transition by updating the AzSDK module -to the latest AzSDK (version 2.11.x). Thus existing CA setups will not get impacted (scanning will continue as earlier). - -Once you migrate, the migration process will create a new CA setup in the subscription using the same settings -that were provided when CA was setup originally. The new CA setup will be 'AzSK'-based and will import the 'AzSK' -module into the automation account. Thereafter, CA scanning will use 'AzSK' and will update to newer releases of -'AzSK' module whenever they become available. - -##### What about CICD extension? -The CICD extension has been revised to reflect the switch from 'AzSDK' to 'AzSK'. -The previous extension will continue to work in the pipeline. Once a subscription has been migrated, you should -just go to the extension UI and select the newest version. - -If you have setup CICD in non-hosted mode, you may have to manually remove the older module as an additional step. - -##### Are my old CA scan logs retained after migration? -Yes. We retain the old CA logs in the (old) storage account within 'AzSDKRG'. The migration process places a 'read' -lock on 'AzSDKRG'. Because of this, you may not be able to migrate to the storage account's blobs and view the logs. -Should you need to view any of the old logs, you can go to the 'AzSDK' resource group and view 'Locks' for it. -Change the lock type from 'read-only' to 'delete' temporarily and download/view and logs you wish to. However, as soon -as you can, please change the lock type back to 'read only'. This lock required so that other users using older 'AzSDK' -modules (prior to AzSDK 2.11.x) should not be able to write to the old RG once migration has been performed. diff --git a/00a-Setup/Readme.md b/00a-Setup/Readme.md index 6aece63d..d598cd36 100644 --- a/00a-Setup/Readme.md +++ b/00a-Setup/Readme.md @@ -1,14 +1,20 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +------------------------------------------------ + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + # Installation Guide ->

IMPORTANT:

If you are from CSE, please install the AzSK via instructions at https://aka.ms/devopskit so that CSE-specific policies are configured for your installation. Do not use the installation instructions on this page. +>

IMPORTANT:

If you are from CSE, please install the AzSK via instructions at https://aka.ms/devopskit/onboarding so that CSE-specific policies are configured for your installation. Do not use the installation instructions on this page. >**Pre-requisites**: > - PowerShell 5.0 or higher. -> - AzureRM Version 5.2.0 +> - Windows OS 1. First verify that prerequisites are already installed: - Ensure that you have PowerShell version 5.0 or higher by typing **$PSVersionTable** in the PowerShell ISE console window and looking at the PSVersion in the output as shown below.) + Ensure that you are using Windows OS and have PowerShell version 5.0 or higher by typing **$PSVersionTable** in the PowerShell ISE console window and looking at the PSVersion in the output as shown below.) If the PSVersion is older than 5.0, update PowerShell from [here](https://www.microsoft.com/en-us/download/details.aspx?id=54616). ![PowerShell Version](../Images/00_PS_Version.PNG) @@ -18,28 +24,34 @@ Install-Module AzSK -Scope CurrentUser ``` -Note: You may need to use `-AllowClobber` and `-Force` options with the Install-Module command -above if you have a different version of AzureRM installed on your machine. -AzSK depends on a specific version of AzureRM and installs that during the installation above. +Note: + +You may need to use `-AllowClobber` and `-Force` options with the Install-Module command +above if you have a different version of Az modules installed on your machine. +AzSK depends on specific version of different Az service modules and installs that during the installation above. +Run command 'Find-Module AzSK -includedependencies' to see all dependencies. + +In version 3.6.x, if you are facing issue during scan, you may have to register "Microsoft.Security" and "Microsoft.PolicyInsights" providers on subscriptions. Refer [link](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-supported-services#portal) for provider registration. + ------------------------------------------------ ### Backward compatibility -As Azure features evolve and add more security controls, "Secure DevOpsKit for Azure" also evolve every month respecting the latest security features. -It is always recommended to run on the latest devops kit module to scan your subscription with the latest rules. +As Azure features evolve and add more security controls, "Secure DevOps Kit for Azure" also evolves every month respecting the latest security features. +It is always recommended to run on the latest DevOps kit module to scan your subscription with the latest rules. -Users who are still using older modules of devops kit continue to work only until N-2 version w.r.t production version e.g. If the current production version is 3.2.x, -then teams can continue to use 3.0.x and 3.1.x. As the version 3.3.x becomes available, automatically 3.0.x would stop working. +Users who are still using older modules of DevOps kit continue to work only until N-2 version w.r.t production version e.g. If the current production version is 3.11.x, +then teams can continue to use 3.9.x and 3.10.x. As the version 3.12.x becomes available, automatically 3.9.x would stop working. -More details on how it impacts each stage of DevOps are shared below: +More details on how it impacts each stage of DevOps kit are shared below: **Adhoc Scans:** -Users running the devops kit scan using N-3 version from their local machine, will start getting an error asking to upgrade as shown below: +Users running the DevOps kit scan using N-3 version from their local machine, will start getting an error asking to upgrade as shown below: ![Install_OlderVersionWarning](../Images/00_Install_OlderVersionWarning.PNG) > **Note:** This restriction has been put in place from AzSDK version 2.8.x and applicable for all future releases. **Continuous Assurance(CA) Scans:** No impact to CA as it would automatically upgrade to latest version. -Before every scan it checks whether there has been a latest release of the devops kit and upgrade itself. +Before every scan it checks whether there has been a latest release of the DevOps kit and upgrade itself. All the further scans would happen using the latest version. **AzSK CICD Extension:** @@ -47,15 +59,15 @@ No impact to default behavior of CICD. It always runs the scan with the latest v If teams have overridden the default behavior by specifying a version number during the build, then the same restriction of N-2 applies here as well. ### Auto Update -It is always recommended to scan your subscription with the latest devops kit module and thus by ensuring to evaluate latest security controls that are available through the module. -"Secure DevOps kit for Azure" module provide different auto update capabilities w.r.t different stages of devops. More details are below: +It is always recommended to scan your subscription with the latest DevOps kit module, thus ensuring to evaluate latest security controls that are available through the module. +"Secure DevOps Kit for Azure" module provides different auto update capabilities w.r.t different stages of devops. More details are below: **Adhoc Scans:** Users running the older version of AzSK scan from their local machine will get a warning as shown in the image below. It would also provide the user with required instructions to upgrade the module. ![Install_Autoupdate](../Images/00_Install_Autoupdate.PNG) -In a scenario where an organization has setup its own instance of "Secure DevOpsKit for Azure", the users can leverage +In a scenario where an organization has setup its own instance of "Secure DevOps Kit for Azure", the users can leverage the auto update feature which has been introduced from the AzSDK version 2.8.x. As shown in the image above, user can either sign up for Autoupdate or go with manual update by running the command below: @@ -64,17 +76,18 @@ As shown in the image above, user can either sign up for Autoupdate or go with m ``` User needs to close and reopen a fresh session once the command is run. -Going forward, if the latest version of devops kit is released, then during execution of any devops kit command it would start the auto update workflow automatically +Going forward, if the latest version of DevOps kit is released, then during execution of any DevOps kit command it would start the auto update workflow automatically as shown in the image below: + ![Install_Autoupdate_Workflow](../Images/00_Install_Autoupdate_Workflow.PNG) Step 1: It would take user consent before it starts the auto update workflow. (1 in the image above)
-Step 2: User need to close all the displayed PS sessions. Typically open PS sessions would lock the module and fail the installation. (2 in the image above)
+Step 2: Users need to close all the displayed PS sessions. Typically open PS sessions would lock the module and fail the installation. (2 in the image above)
Step 3: Even the current session must be closed. It would again take the user consent before it starts the auto update flow to avoid the loss of any unsaved work. (3 in the image above) **Continuous Assurance(CA) Scans:** -The devops kit module running the scans through CA, auto updates itself. Every scan would initially check if any new version has been released and auto-upgrade the installed module to the latest version. +The DevOps kit module running the scans through CA, auto updates itself. Every scan would initially check if any new version has been released and auto-upgrade the installed module to the latest version. No action is required from the user. Users can also run the command below to confirm the same: @@ -86,10 +99,34 @@ Users can also run the command below to confirm the same: **AzSK CICD Extension** AzSK CICD extension will always run the scan using latest module of AzSK from the gallery. This is the default behavior in the case of both hosted and non-hosted agents. -You could find more details about CICD [here.](../03-Security-In-CICD/Readme.md) +You could find more details about CICD [here](../03-Security-In-CICD/Readme.md). ------------------------------------------------ ### FAQs + +#### Getting exception: Package 'Az.Accounts' failed to be installed because End of Central Directory record could not be found. + +Recently we have seen some users are facing issue during installation of latest AzSK module from PSGallery. AzSK is mainly dependant on Az module versions and its failing to install specific versions. We are investigating more on issue. You can use below method to install module from AzSK repository. + +```PowerShell +$AzSKModuleRepoPath = "https://azsdkossep.azureedge.net/3.7.0/AzSK.zip" + +#Copy module zip to temp location +$CopyFolderPath = $env:temp + "\AzSKTemp\" +if(-not (Test-Path -Path $CopyFolderPath)) +{ + mkdir -Path $CopyFolderPath -Force | Out-Null +} +$ModuleFilePath = $CopyFolderPath + "AzSK.zip" +Invoke-WebRequest -Uri $AzSKModuleRepoPath -OutFile $ModuleFilePath + +#Extract zip file to module location +Expand-Archive -Path $ModuleFilePath -DestinationPath "$Env:USERPROFILE\documents\WindowsPowerShell\modules" -Force + +#Clean up temp location +Remove-Item –path $CopyFolderPath –recurse +``` + #### Should I run PowerShell ISE as administrator or regular user? Please run PowerShell ISE as a regular user. The AzSK has been thoroughly tested to run in normal user (non-elevated) mode. As much as possible, please do not launch your PS sessions in "Administrator" mode. There is nothing that the AzSK does that needs elevated privileges on the local system. Even the installation command itself uses a '-Scope CurrentUser' parameter internally. @@ -106,45 +143,108 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser The execution policy setting will be remembered and all future PS consoles opened in non-Admin (CurrentUser) mode will apply the 'RemoteSigned' execution policy. #### Error message: "PackageManagement\Install-Package: cannot process argument transformation on parameter 'InstalledModuleInfo'..." -If you have installed AzureRM PowerShell using Azure SDK in your machine, it typically get installed in Program Files. You could run the below command to confirm + + +If you have installed Az PowerShell using Azure SDK in your machine, it typically gets installed in Program Files. You could run the below command to confirm ```PowerShell - Get-Module -Name AzureRM* -ListAvailable + Get-Module -Name Az.* -ListAvailable ``` If this is the case, then you need to remove the Azure PowerShell modules installed through Azure SDK completely from the Program Files. You could also take back up in case if you need. -AzSK also need AzureRM modules. But it would download from PSGallery instead of from Azure SDK. This downloading of AzureRM modules from PS Gallery would conflict with AzureRM modules installed through Azure SDK. -After cleanup, If you again the run the below command, it would fetch AzureRM version 5.2.0 by default into the current user scope instead of in Program Files. +AzSK also needs Az modules. But it would download from PSGallery instead of from Azure SDK. This downloading of Az modules from PS Gallery would conflict with Az modules installed through Azure SDK. +After cleanup, If you again the run the below command, it would fetch Az version 1.1.0 by default into the current user scope instead of in Program Files. ```PowerShell Install-Module AzSK -Scope CurrentUser -AllowClobber ``` -In case you still need to use the other version of AzureRm (that you removed), you can install it from PS Gallery using the command below: +In case you still need to use the other version of Az (that you removed), you can install it from PS Gallery using the command below: ```PowerShell -Install-Module AzureRM -Scope CurrentUser -AllowClobber -RequiredVersion +Install-Module Az -Scope CurrentUser -AllowClobber -RequiredVersion ``` > Note: If *"-AllowClobber"* option is not available in your version of PS, then replace that with *"-Force"* -If you happen to have multiple versions of AzureRM, then it depends on which version of the module loads first in the PS session. In that case, to avoid confusion, close the installer PS session and in a new PS session run the following first: +If you happen to have multiple versions of Az, then it depends on which version of the module loads first in the PS session. In that case, to avoid confusion, close the installer PS session and in a new PS session run the following first: ```PowerShell Import-Module AzSK ``` -Then you can run one or more AzSK commands or other AzureRm commands. The *"Import-Module"* ensures that the right version of AzureRM gets loaded into the current session. +Then you can run one or more AzSK commands or other Az commands. The *"Import-Module"* ensures that the right version of Az gets loaded into the current session. -#### Error message: "WARNING: The version '3.x.y' of module 'AzureRM.Profile' is currently in use. Retry the operation after closing..." -If you see multiple warning such as the above during setup, it is likely that one or more PowerShell instances are running and have AzureRm modules loaded which are conflicting with the AzSK installation. In such as case, it is best to ensure that all PS sessions (including the current one) are closed and start the installer in a fresh PS ISE session. +#### Error message: "WARNING: The version '1.x.y' of module 'Az.Accounts' is currently in use. Retry the operation after closing..." +If you see multiple warning such as the above during setup, it is likely that one or more PowerShell instances are running and have Az modules loaded which are conflicting with the AzSK installation. In such as case, it is best to ensure that all PS sessions (including the current one) are closed and start the installer in a fresh PS ISE session. In dire circumstances, you may need to close/kill all instances of PowerShell sessions running on your system (including VS if you have PS plugin installed). In that case, make sure you have saved any work in those sessions and then run the following in a Windows Cmd console: ```PowerShell taskkill /im PowerShell_ise.exe & taskkill /im PowerShell.exe & taskkill /im PowerShellToolsProcessHost.exe ``` #### Error message: "The property 'Id' cannot be found on this object. Verify that the property exists..." -This is typically caused by a version mis-match for underlying AzureRm PowerShell modules that are used by AzSK! The AzSK installation process will typically install AzureRm modules corresponding to the version that it depends on. However, it is possible that you also have a previous version of AzureRm on your machine. +This is typically caused by a version mis-match for underlying Az PowerShell modules that are used by AzSK! The AzSK installation process will typically install Az modules corresponding to the version that it depends on. However, it is possible that you also have a previous version of Az on your machine. PowerShell works with the concept of 'sessions'. Each PowerShell ISE or command prompt window is its own independent session. By default, when any cmdlet is run, PS will load the corresponding module (code) in the memory for that session. After that, subsequent references to cmdlets in that module will use the loaded module. Usually, the module loading follows a particular heuristic (based on version number, PS module path order, admin v. non-admin PS launch mode, etc.) -The above error message is an indication that an AzSK cmdlet is being run in a PowerShell session that already had an older version of AzureRm loaded in memory (which may be due to something as simple as doing a Login-AzureRmAccount and *then* installing AzSK in that session). In most circumstances, one of the following remedies should work: -- Close the PS session and open a new one. In the new session, do an "*Import-Module AzureRm -RequiredVersion 5.2.0*" before running anything else (e.g., Login-AzureRmAccount) -- Close the PS session and open a new one. In the new session, do an "*Import-Module AzSK*" before running anything else. (This will force-load the correct version of AzureRm that AzSK needs.). - - If you suspect that you may have multiple versions of AzSK itself installed, then use "*Import-Module AzSK -RequiredVersion 2.5.0*" (August release). +The above error message is an indication that an AzSK cmdlet is being run in a PowerShell session that already had an older version of Az loaded in memory (which may be due to something as simple as doing a Connect-AzAccount and *then* installing AzSK in that session). In most circumstances, one of the following remedies should work: +- Close the PS session and open a new one. In the new session, do an "*Import-Module Az -RequiredVersion 1.1.0*" before running anything else (e.g., Connect-AzAccount) +- Close the PS session and open a new one. In the new session, do an "*Import-Module AzSK*" before running anything else. (This will force-load the correct version of Az that AzSK needs.). + - If you suspect that you may have multiple versions of AzSK itself installed, then use "*Import-Module AzSK -RequiredVersion 3.11.0*" (March 2019 release). #### Message: "Warning : Microsoft Azure PowerShell collects data about how users use PowerShell cmdlets..." -The AzSK depends upon AzureRm PowerShell modules. AzureRm modules are created/maintained by the Azure product team and provide the core PowerShell libraries to interact with different Azure services. For example, you'd use the AzureRm Storage module to create/work with a storage account, etc. +The AzSK depends upon Az PowerShell modules. Az modules are created/maintained by the Azure product team and provide the core PowerShell libraries to interact with different Azure services. For example, you'd use the Az Storage module to create/work with a storage account, etc. + +The AzSK setup installs the required version of Az. It is possible that this is the first time your system is being setup for Az. In such a situation, you will get a 'data collection' related notice/warning from Az. You can choose to 'accept' or 'decline' permission to collect data. The AzSK functionality will not be affected by that. + +#### When will AzSK support the newest Az dependencies? Can I run both side by side? In the meantime, what if I need to run both AzSK and the new version of Az modules (for different tasks)? +At any time, AzSK is bound to a specific version of Az service modules. We have found that it keeps our dependencies in check and limits randomizations from minor version updates of one of the many modules that ship under the "Az umbrella". + +However, after each major update to Az, we wait for a dot-release and migrate AzSK to the latest version. This usually happens within a couple of months after the major Az release. + +In the interim, if you need to use AzSK as well as the latest Az (for other tasks), this is how you can do it. (We assume that you already have the latest AzSK installed which, in turn, will ensure that you have the version of Az modules that AzSK requires). +Install the newest Az from a fresh PS console if you haven't done so. +Use separate PS consoles for AzSK and (newer) Az modules work. +For the AzSK console, always start with the following command: +```PowerShell +Import-Module AzSK +``` +This will automatically cause AzSK to load the version of Az modules it requires as opposed to the newest one. Run AzSK commands as needed in this session. +For the (new) Az console, just run whatever Az commands you need to there. The latest installed version of Az will automatically get loaded and used for those. (Do not run AzSK commands in this console.) + +Just note that this assumes that both AzSK and Az were installed with '-Scope CurrentUser'. If a newer Az is installed without an explicit 'CurrentUser' scope, it is possible that by default different versions of Az modules may get loaded. In such a situation, it is better to explicitly load the version needed with a '-RequiredVersion' flag (or full path to module). Basically, remember that PS will search for a module in the order folders are listed in $Env:PSModulePath and load the first module that exports the function being used. + +#### How often should I upgrade my installation of AzSK? How long will it take? +The AzSK team releases a new version of AzSK at the end of each monthly sprint. You should aim to use the latest release always. So, as a regular user, you should upgrade AzSK each month. + +Being on the latest release ensures that you have the latest features, most up to date control evaluation code, coverage for latest Security Verification Tests (SVTs), etc. Note that, when you run any AzSK command, if there is a newer version of AzSK available, the command will tell you about it (at the very top). + +Note that, the first time you installed AzSK, it perhaps took a few extra minutes because of the dependencies that had to be installed (especially Az). In most subsequent installations, it will just need to fetch the latest AzSK modules. This will hardly take a couple of minutes. + + +### Message: "WARNING: AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session or used in the same script or runbook." + +This warning pops up because both Az and AzureRM modules are loaded in the same PowerShell session. This must be occurring because you might have tried executing an Az-based command with AzureRM module already loaded (or vice versa). + +> **Note:** The big change in the latest AzSK release (v3.11.0) is the migration of the DevOps Kit from AzureRM to the new Az-* PowerShell libraries. + +Steps to remediate: + +- Run 'Import-Module' AzSK in a fresh PowerShell session as the first command. + +- Use 'Connect-AzAccount' to login to your subscription (if using AzSK v3.11.0). + +### How to update policy endpoint to latest policy store location? +While running AzSK commands, if you get warning like this, +> **Important**: Your AzSK setup is using a policy endpoint that may be deprecated soon as part of AzSK sunset. Please use steps here: https://aka.ms/devopskit/sunset/osspolicy to use a stable policy store location. + +then this indicates that online policy store url in your environment is pointing to policy endpoint which might get deprecated soon as part of AzSK sunset. To keep using AzSK cmdlets without any issues, you need to update policy endpoint to stable policy store location by following below mentioned steps: + +**Step 1**: Import 'AzSK' module in a fresh session. + + ```PowerShell + Import-Module AzSK + ``` + +**Step 2**: Run following command to update policy endpoint. + +```PowerShell + Set-AzSKPolicySettings -OnlinePolicyStoreUrl "https://raw.githubusercontent.com/azsk/DevOpsKit/master/src/oss-config/`$Version/`$FileName" +``` +**Step 3**: Clear the current session state. + +```PowerShell + Clear-AzSKSessionState +``` -The AzSK setup installs the required version of AzureRm. It is possible that this is the first time your system is being setup for AzureRm. In such a situation, you will get a 'data collection' related notice/warning from AzureRm. You can choose to 'accept' or 'decline' permission to collect data. The AzSK functionality will not be affected by that. diff --git a/00b-Getting-Started/GettingStarted_AzureServiceSecurity.md b/00b-Getting-Started/GettingStarted_AzureServiceSecurity.md index c0e2002a..d5fb981b 100644 --- a/00b-Getting-Started/GettingStarted_AzureServiceSecurity.md +++ b/00b-Getting-Started/GettingStarted_AzureServiceSecurity.md @@ -1,16 +1,21 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. ## Scan your cloud application (Azure resources) for security vulnerabilities ###### :clock10: 30 minutes to complete -The AzSK contains cmdlets that dev ops teams can use to regularly keep their cloud applications +The AzSK contains cmdlets that devops teams can use to regularly keep their cloud applications secure during the multiple sprints involving prototyping, core solution development, integration and deployment. -These scripts are called Security Verification Tests (SVT) and cover all prominent features in +These scripts are called Security Verification Tests (SVTs) and cover all prominent features in Azure (e.g., Web Apps, Storage, SQL DB, Key Vault, etc.). Each SVT corresponds to a particular Azure feature or service and automates checks for secure configuration and security best practices for that Azure service. > Note: Ensure that you already have the latest version of AzSK installed on your machine. -> If not, please follow instruction [here.](../00a-Setup/Readme.md) +> If not, please follow instructions [here](../00a-Setup/Readme.md). **Step 1**: Run the command below after replacing `` with your Azure SubscriptionId and ` with a comma-separated list of resource groups where your resources are hosted. @@ -23,7 +28,7 @@ cloud resources that constitute the application. The AzSK also supports other ways of representing an application. For instance, you can also make use of the 'tags' parameter to scan only resources with -a specific tag value. More details can be found [here.](../02-Secure-Development/Readme.md#execute-svts-for-specific-resource-groups-or-tagged-resources) +a specific tag value. More details can be found [here](../02-Secure-Development/Readme.md#execute-svts-for-specific-resource-groups-or-tagged-resources). When the command runs, you will start seeing output such as the following in the PowerShell console. Time required for execution will depend on the number of resources that are being scanned. @@ -54,8 +59,8 @@ the resource groups under which the resources themselves are organized in your s ![00_ServiceSecurity_OP_Folder](../Images/00_ServiceSecurity_OP_Folder.PNG) We can now examine the CSV file to see the control summary. (It opens by default in XLS and you can -use "Format as Table", "Hide Columns", "Filter", etc., to quickly look at controls that have "Failed" -or ones that are marked "Verify" (latter represents controls that need manual confirmations). +use "Format as Table", "Hide Columns", "Filter", etc., to quickly look at the controls that have "Failed" +or the ones that are marked "Verify" (latter represents controls that need manual confirmations). ![00_Service_Status_OP_CSV](../Images/00_Service_Status_OP_CSV.PNG) @@ -74,4 +79,4 @@ Congratulations! You have completed this section of the Getting Started guide su **Next steps** To get more details and understand SVTs and other secure development features of the AzSK further, -please refer [here.](../02-Secure-Development/Readme.md) +please refer [here](../02-Secure-Development/Readme.md). diff --git a/00b-Getting-Started/GettingStarted_PowerShellTipsAzSK.md b/00b-Getting-Started/GettingStarted_PowerShellTipsAzSK.md index 981bfebc..aa8e32e0 100644 --- a/00b-Getting-Started/GettingStarted_PowerShellTipsAzSK.md +++ b/00b-Getting-Started/GettingStarted_PowerShellTipsAzSK.md @@ -1,3 +1,8 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # PowerShell tips for new AzSK Users @@ -158,7 +164,7 @@ you have to type a long command with many parameters. Here's an example: ###### Without backtick: single long line ```PowerShell -Install-AzSKContinuousAssurance -SubscriptionId '2fedc012-3456-7890-abcd-ef0123456479' -ResourceGroupNames 'RG1, RG2, RG3' -OMSWorkspaceId $omswsId '1fedcba0-1234-5678-9abc-fedcba012345' -OMSSharedKey 'O1qaz2wsx3edc4rfv5tgb.........9olp0plofA==' +Install-AzSKContinuousAssurance -SubscriptionId '2fedc012-3456-7890-abcd-ef0123456479' -ResourceGroupNames 'RG1, RG2, RG3' -LAWSId $lawsId '1fedcba0-1234-5678-9abc-fedcba012345' -LAWSSharedKey 'O1qaz2wsx3edc4rfv5tgb.........9olp0plofA==' ``` ###### With backtick: for multi-line continuation @@ -167,8 +173,8 @@ Install-AzSKContinuousAssurance -SubscriptionId '2fedc012-3456-7890-abcd-ef01234 Install-AzSKContinuousAssurance ` -SubscriptionId '2fedc012-3456-7890-abcd-ef0123456479' ` -ResourceGroupNames 'RG1, RG2, RG3' ` - -OMSWorkspaceId $omswsId '1fedcba0-1234-5678-9abc-fedcba012345' ` - -OMSSharedKey 'O1qaz2wsx3edc4rfv5tgb.........9olp0plofA==' + -LAWSId $lawsId '1fedcba0-1234-5678-9abc-fedcba012345' ` + -LAWSSharedKey 'O1qaz2wsx3edc4rfv5tgb.........9olp0plofA==' ``` [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) @@ -182,17 +188,17 @@ PS C:\> Get-Command -Module AzSK CommandType Name Version Source ----------- ---- ------- ------ -Function Get-AzSKAccessToken 3.0.0 AzSK -Function Get-AzSKAzureServicesSecurityStatus 3.0.0 AzSK -Function Get-AzSKContinuousAssurance 3.0.0 AzSK -Function Get-AzSKControlsStatus 3.0.0 AzSK -Function Get-AzSKExpressRouteNetworkSecurityStatus 3.0.0 AzSK -Function Get-AzSKSubscriptionSecurityStatus 3.0.0 AzSK -Function Get-AzSKSupportedResourceTypes 3.0.0 AzSK -Function Install-AzSKContinuousAssurance 3.0.0 AzSK -Function Install-AzSKOMSSolution 3.0.0 AzSK -Function Remove-AzSKAlerts 3.0.0 AzSK -Function Remove-AzSKARMPolicies 3.0.0 AzSK +Function Get-AzSKAccessToken 3.11.0 AzSK +Function Get-AzSKAzureServicesSecurityStatus 3.11.0 AzSK +Function Get-AzSKContinuousAssurance 3.11.0 AzSK +Function Get-AzSKControlsStatus 3.11.0 AzSK +Function Get-AzSKExpressRouteNetworkSecurityStatus 3.11.0 AzSK +Function Get-AzSKSubscriptionSecurityStatus 3.11.0 AzSK +Function Get-AzSKSupportedResourceTypes 3.11.0 AzSK +Function Install-AzSKContinuousAssurance 3.11.0 AzSK +Function Install-AzSKMonitoringSolution 3.11.0 AzSK +Function Remove-AzSKAlerts 3.11.0 AzSK +Function Remove-AzSKARMPolicies 3.11.0 AzSK ... (truncated) ``` @@ -202,28 +208,31 @@ PS C:\> Get-Command -Name Get* -Module AzSK CommandType Name Version Source ----------- ---- ------- ------ -Function Get-AzSKAccessToken 3.0.0 AzSK -Function Get-AzSKAzureServicesSecurityStatus 3.0.0 AzSK -Function Get-AzSKContinuousAssurance 3.0.0 AzSK -Function Get-AzSKControlsStatus 3.0.0 AzSK -Function Get-AzSKExpressRouteNetworkSecurityStatus 3.0.0 AzSK -Function Get-AzSKSubscriptionSecurityStatus 3.0.0 AzSK -Function Get-AzSKSupportedResourceTypes 3.0.0 AzSK +Function Get-AzSKAccessToken 3.11.0 AzSK +Function Get-AzSKARMTemplateSecurityStatus 3.11.0 AzSK +Function Get-AzSKAzureServicesSecurityStatus 3.11.0 AzSK +Function Get-AzSKContinuousAssurance 3.11.0 AzSK +Function Get-AzSKControlsStatus 3.11.0 AzSK +Function Get-AzSKExpressRouteNetworkSecurityStatus 3.11.0 AzSK +Function Get-AzSKInfo 3.11.0 AzSK +Function Get-AzSKOrganizationPolicyStatus 3.11.0 AzSK +Function Get-AzSKSubscriptionSecurityStatus 3.11.0 AzSK +Function Get-AzSKSupportedResourceTypes 3.11.0 AzSK ``` ###### Get all AzSK commands have 'Subscription' anywhere in the name ```PowerShell PS C:\> Get-Command -Name *Subscription* -Module AzSK -CommandType Name Version Source ------------ ---- ------- ------ -Function Get-AzSKSubscriptionSecurityStatus 3.0.0 AzSK -Function Remove-AzSKSubscriptionRBAC 3.0.0 AzSK -Function Remove-AzSKSubscriptionSecurity 3.0.0 AzSK -Function Repair-AzSKSubscriptionSecurity 3.0.0 AzSK -Function Set-AzSKSubscriptionRBAC 3.0.0 AzSK -Function Set-AzSKSubscriptionSecurity 3.0.0 AzSK -Function Update-AzSKSubscriptionSecurity 3.0.0 AzSK +CommandType Name Version Source +----------- ---- ------- ------ +Function Get-AzSKSubscriptionSecurityStatus 3.11.0 AzSK +Function Remove-AzSKSubscriptionRBAC 3.11.0 AzSK +Function Remove-AzSKSubscriptionSecurity 3.11.0 AzSK +Function Repair-AzSKSubscriptionSecurity 3.11.0 AzSK +Function Set-AzSKSubscriptionRBAC 3.11.0 AzSK +Function Set-AzSKSubscriptionSecurity 3.11.0 AzSK +Function Update-AzSKSubscriptionSecurity 3.11.0 AzSK ``` ###### Get all commands from *any* available module (not just AzSK) that start with 'Backup' @@ -232,18 +241,13 @@ PS C:\> Get-Command -name Backup* CommandType Name Version Source ----------- ---- ------- ------ -Function Backup-BitLockerKeyProtector 1.0.0.0 BitLocker -Cmdlet Backup-AzureKeyVaultKey 4.1.0 AzureRM -Cmdlet Backup-AzureKeyVaultKey 3.1.0 AzureRM.KeyVault -Cmdlet Backup-AzureKeyVaultSecret 4.1.0 AzureRM -Cmdlet Backup-AzureKeyVaultSecret 3.1.0 AzureRM.KeyVault -Cmdlet Backup-AzureRmApiManagement 4.1.0 AzureRM -Cmdlet Backup-AzureRmApiManagement 4.1.0 AzureRM.ApiManagement -Cmdlet Backup-AzureRmBackupItem 4.1.0 AzureRM -Cmdlet Backup-AzureRmBackupItem 3.1.0 AzureRM.Backup -Cmdlet Backup-AzureRmRecoveryServicesBackupItem 4.1.0 AzureRM -Cmdlet Backup-AzureRmRecoveryServicesBackupItem 3.1.0 AzureRM.RecoverySe... -Cmdlet Backup-WebConfiguration 1.0.0.0 WebAdministration +Function Backup-BitLockerKeyProtector 1.0.0.0 BitLocker +Function BackupToAAD-BitLockerKeyProtector 1.0.0.0 BitLocker +Cmdlet Backup-AzApiManagement 1.0.0 Az.ApiManagement +Cmdlet Backup-AzKeyVaultCertificate 1.0.0 Az.KeyVault +Cmdlet Backup-AzKeyVaultKey 3.1.0 Az.KeyVault +Cmdlet Backup-AzKeyVaultManagedStorageAccount 4.1.0 Az.KeyVault +Cmdlet Backup-AzKeyVaultSecret 4.1.0 Az.KeyVault ``` [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) @@ -263,18 +267,18 @@ SYNOPSIS SYNTAX Update-AzSKContinuousAssurance -SubscriptionId -TargetSubscriptionIds - [-ResourceGroupNames ] [-OMSWorkspaceId ] [-OMSSharedKey ] + [-ResourceGroupNames ] [-LAWSId ] [-LAWSSharedKey ] [-AzureADAppName ] [-FixRuntimeAccount] [-FixModules] [-DoNotOpenOutputFolder] [-LoggingOption {Central | Self | Both}] -Preview [] Update-AzSKContinuousAssurance -SubscriptionId [-ResourceGroupNames ] - [-OMSWorkspaceId ] [-OMSSharedKey ] [-AzureADAppName ] + [-LAWSId ] [-LAWSSharedKey ] [-AzureADAppName ] [-FixRuntimeAccount] [-FixModules] [-DoNotOpenOutputFolder] [] DESCRIPTION This command is helpful if you want to update any of the following properties. 1. App Resource - Groups 2. OMS Workspace ID 3. OMS Shared Key + Groups 2. Log Analytics Workspace ID 3. Log Analytics Workspace Shared Key 4. Connection in Run as Account 5. Update/Renew Certificate in Run as Account @@ -297,12 +301,42 @@ for the module that supports it and loads the newest version of the module avail You can see the modules that are loaded in the current session using "Get-Module" ```PowerShell -PS C:\> get-module +PS C:\> Get-Module ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- -Script 3.0.0 AzSK {Get-AzSKAccessToken, Get-AzSKAzur... -Script 4.1.0 AzureRM {Add-AzureAnalysisServicesAccount, A... +Script 3.11.0 AzSK {Clear-AzSKSessionState, Get-AzSKAcc... +Script 1.2.1 Az.Accounts {Add-AzEnvironment, Clear-AzContext,... +Script 1.0.0 Az.AnalysisServices {Add-AzAnalysisServicesAccount, Expo... +Script 1.0.0 Az.ApiManagement {Add-AzApiManagementApiToProduct, Ad... +Script 1.0.0 Az.ApplicationInsights {Get-AzApplicationInsights, Get-AzAp... +Script 1.0.0 Az.Automation {Export-AzAutomationDscConfiguration... +Script 1.0.0 Az.Batch {Disable-AzBatchAutoScale, Disable-A... +Script 1.0.0 Az.Cdn {Confirm-AzCdnEndpointProbeURL, Disa... +Script 1.1.0 Az.Compute {Add-AzContainerServiceAgentPoolProf... +Script 1.0.0 Az.ContainerInstance {Get-AzContainerGroup, Get-AzContain... +Script 1.0.0 Az.ContainerRegistry {Get-AzContainerRegistry, Get-AzCont... +Script 1.0.0 Az.DataFactory {Get-AzDataFactory, Get-AzDataFactor... +Script 1.0.0 Az.DataLakeAnalytics {Add-AzDataLakeAnalyticsDataSource, ... +Script 1.0.1 Az.DataLakeStore {Add-AzDataLakeStoreFirewallRule, Ad... +Script 1.0.0 Az.EventHub {Get-AzEventHub, Get-AzEventHubAutho... +Script 1.0.0 Az.HDInsight {Add-AzHDInsightClusterIdentity, Add... +Script 1.0.0 Az.KeyVault {Add-AzKeyVaultCertificate, Add-AzKe... +Script 1.1.0 Az.LogicApp {Get-AzIntegrationAccount, Get-AzInt... +Script 1.0.0 Az.Monitor {Add-AzAutoscaleSetting, Add-AzLogPr... +Script 1.0.0 Az.Network {Add-AzApplicationGatewayAuthenticat... +Script 1.0.0 Az.NotificationHubs {Get-AzNotificationHub, Get-AzNotifi... +Script 1.0.0 Az.OperationalInsights {Disable-AzOperationalInsightsIISLog... +Script 1.0.0 Az.PolicyInsights {Get-AzPolicyEvent, Get-AzPolicyReme... +Script 1.0.0 Az.RedisCache {Export-AzRedisCache, Get-AzRedisCac... +Script 1.1.0 Az.Resources {Add-AzADGroupMember, Export-AzResou... +Script 1.0.0 Az.ServiceBus {Complete-AzServiceBusMigration, Get... +Script 1.0.0 Az.ServiceFabric {Add-AzServiceFabricApplicationCerti... +Script 1.0.1 Az.Sql {Add-AzSqlDatabaseToFailoverGroup, A... +Script 1.0.1 Az.Storage {Add-AzRmStorageContainerLegalHold, ... +Script 1.0.0 Az.StreamAnalytics {Get-AzStreamAnalyticsDefaultFunctio... +Script 1.0.0 Az.TrafficManager {Add-AzTrafficManagerCustomHeaderToE... +Script 1.0.1 Az.Websites {Edit-AzWebAppBackupConfiguration, E... Script 1.0.0.0 ISE {Get-IseSnippet, Import-IseSnippet, ... Manifest 3.1.0.0 Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoi... Manifest 3.0.0.0 Microsoft.PowerShell.Security {ConvertFrom-SecureString, ConvertTo... @@ -315,11 +349,11 @@ Manifest 2.0.0.0 PSWorkflow {New-PSWorkflowExecuti You can also check for a specific module using "Get-Module 'module-name'" ```PowerShell -PS C:\> get-module azsk +PS C:\> Get-Module AzSK ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- -Script 3.0.0 AzSK {Get-AzSKAccessToken, Get-AzSKAzur... +Script 3.11.0 AzSK {Get-AzSKAccessToken, Get-AzSKAzur... ``` Version conflicts happen if, due to some action, multiple versions of the same module get loaded within a single session. For example, you may notice that a new version of AzSK is available (based on a warning from a scan command) @@ -336,29 +370,29 @@ Error: The property 'Xyz' cannot be found on this object. Verify that the proper The remedy for this is to run a fresh installation using the "iwr" command in a *fresh* PS session. -Another common version conflict happens if you have many (old) versions of AzureRm installed. AzureRm is -a core dependency for AzSK. If a different version of AzureRm is loaded in a session and an AzSK command is +Another common version conflict happens if you have many (old) versions of Az installed. Az is +a core dependency for AzSK. If a different version of Az is loaded in a session and an AzSK command is run, it may struggle to find the type information it is counting on for one or more Azure resource types. (For e.g., -a Storage object from an old AzureRm version will not have the fileEncryption property exposed.) +a Storage object from an old Az version will not have the fileEncryption property exposed.) An easy way you can get into this situation is if you are using the 'Command Add-on' pane. It often shows many -options for basic commands like 'Login-AzureRmAccount'. You may choose any one of them thinking they are +options for basic commands like 'Connect-AzAccount'. You may choose any one of them thinking they are the same thing. Even if that may be the case, choosing to run one of them will cause the corresponding version -of AzureRm to get loaded into your session. If that's not the version AzSK needs, then the same type conflict -issue will pop up soon as you start using AzSK commands. +of Az to get loaded into your session. If that's not the version AzSK needs, then the same type conflict +issue will pop up as soon as you start using AzSK commands. -An easy remedy for this is to ensure that the correct version of AzureRm gets loaded by using any of these options: -1) Just do an "import-module AzSK" first thing after opening a new PS session. This will internally load the correct AzureRm. -2) Else, run any AzSK command (e.g., Get-AzSKSubscriptionSecurityStatus). This will trigger the Azure login flow and cause the correct AzureRm to get loaded. -3) Else, explicitly load the AzureRm version required for AzSK (currently it is 4.1.0) using 'import-module AzureRm -Version 4.1' first thing in a new session. +An easy remedy for this is to ensure that the correct version of Az gets loaded by using any of these options: +1) Do an "Import-Module AzSK" first thing after opening a new PS session. This will internally load the correct Az. +2) Else, run any AzSK command (e.g., Get-AzSKSubscriptionSecurityStatus). This will trigger the Azure login flow and cause the correct Az to get loaded. +3) Else, explicitly load the Az version required for AzSK (currently it is 1.1.0) using 'Import-Module Az -Version 1.1' first thing in a new session. [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) ### Listing your subscriptions -A lot of AzSK commands need you to specify subscription id. To get the subscription id for any particular subscription -you needn't go to the portal. The following command can quickly list all subscriptions by their name and subscription id. +A lot of AzSK commands need you to specify subscription ID. To get the subscription ID for any particular subscription +you needn't go to the portal. The following command can quickly list all subscriptions by their name and subscription ID. ```PowerShell -PS C:\> Get-AzureRmSubscription | FT Name, Id +PS C:\> Get-AzSubscription | FT Name, Id Name Id ---- -- @@ -370,14 +404,14 @@ DSRE-DevTest-Subscription-01 cfeabcde-f012-3456-7890-abcdef01234d ... ... ``` -Note that the pipe character "|" is used to send the output of the Get-AzureRmSubscription command to a formatting helper "FT". +Note that the pipe character "|" is used to send the output of the Get-AzSubscription command to a formatting helper "FT". Here FT is short for "Format-Table" which lets us pick specific fields to display in tabular form. So the overall command means -"Get a list of subscriptions I have access to and show them in tabular form only displaying the Name and Id fields for each." +"Get a list of subscriptions I have access to and show them in tabular form, only displaying the Name and Id fields for each." If you do not specify the "| FT Name, Id" part, you will get the output in a list format as below: ```PowerShell -PS C:\> Get-AzureRmSubscription +PS C:\> Get-AzSubscription Name : MSFT-SRA-05 Id : 0feabcde-f012-3456-7890-abcdef01234f @@ -395,7 +429,7 @@ TenantId : 7fedcba0-1234-8765-abcd-f01234567897 State : Enabled ``` Note that because we did not specify any field selectors, all default fields of each subscription are displayed in the list. -If we were interested only in the name and tenant id in *list* format, we would run "Get-AzureRmSubscription | FL Name, TenantId". +If we were interested only in the name and tenant id in *list* format, we would run "Get-AzSubscription | FL Name, TenantId". The "| FT" and "| FL" options are very handy in many other situations. We will see some more examples below. @@ -404,61 +438,51 @@ The "| FT" and "| FL" options are very handy in many other situations. We will s ### Switching to another subscription -Normally, the AzSK command that you run will switch your context to the subscription Id you specified. If you explicitly want -to switch to some subscription (e.g., to run AzureRm commands to examine resources in that subscription), you can do so using either of -the Select-AzureRmSubscription or Set-AzureRmContext commands (both take either subscriptionName or subscriptionId as a parameter). +Normally, the AzSK command that you run will switch your context to the subscription ID you specified. If you explicitly want +to switch to some subscription (e.g., to run Az commands to examine resources in that subscription), you can do so using either of +the Select-AzContext or Set-AzContext commands (both take either subscriptionName or subscriptionId as a parameter). ```PowerShell -PS C:\> Select-AzureRmSubscription -SubscriptionName 'MSFT-SRA-04' -Environment : AzureCloud -Account : abc@contoso.com -TenantId : 7fedcba0-1234-8765-abcd-f01234567897 -SubscriptionId : 2feabcde-f012-3456-7890-abcdef012349 -SubscriptionName : MSFT-SRA-04 -CurrentStorageAccount : - - -PS C:\> Set-AzureRmContext -SubscriptionId '2feabcde-f012-3456-7890-abcdef012349' -Environment : AzureCloud -Account : abc@contoso.com -TenantId : 7fedcba0-1234-8765-abcd-f01234567897 -SubscriptionId : 2feabcde-f012-3456-7890-abcdef012349 -SubscriptionName : MSFT-SRA-04 -CurrentStorageAccount : +PS C:\> Select-AzContext -Name 'MSFT-SRA-04' +Name Account SubscriptionName Environment TenantId +---- ------- ---------------- ----------- -------- +MSFT-SRA-04 abc@contoso.com Subsctiption1 AzureCloud 72f988bf-86f1-41af-91ab-2d7cd01... + +PS C:\> Set-AzContext -SubscriptionId '2feabcde-f012-3456-7890-abcdef012349' +Name Account SubscriptionName Environment TenantId +---- ------- ---------------- ----------- -------- +MSFT-SRA-04 abc@contoso.com Subsctiption1 AzureCloud 72f988bf-86f1-41af-91ab-2d7cd01... ``` ```PowerShell -You can use the 'Get-AzureRmContext' command to find out which subscription is currently active (target) in the AzureRm context. -PS C:\> Get-AzureRmContext -Environment : AzureCloud -Account : abc@contoso.com -TenantId : 7fedcba0-1234-8765-abcd-f01234567897 -SubscriptionId : 2feabcde-f012-3456-7890-abcdef012349 -SubscriptionName : MSFT-SRA-04 -CurrentStorageAccount : +You can use the 'Get-AzContext' command to find out which subscription is currently active (target) in the Az context. +PS C:\> Get-AzContext +Name Account SubscriptionName Environment TenantId +---- ------- ---------------- ----------- -------- +MSFT-SRA-04 abc@contoso.com Subsctiption1 AzureCloud 72f988bf-86f1-41af-91ab-2d7cd01... ``` [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) ### Use variables effectively -You can avoid repetition of scripts by putting commonly needed values in variables towards the top of your scripts. You can then use -'Run Selection' to set their values up once and then repeat commands without having to edit everywhere. +You can avoid repetition of scripts by putting commonly needed values in variables at the top of your scripts. You can then use +'Run Selection' to set their values once and then repeat commands without having to edit everywhere. -As a simple example, because subscriptionId is required in many places we can do the following: +As a simple example, because SubscriptionId is required in many places we can do the following: ```PowerShell $subId = '2feabcde-f012-3456-7890-abcdef012349' -Set-AzureRmContext -SubscriptionId $subId +Set-AzContext -SubscriptionId $subId Get-AzSKSubscriptionSecurityStatus -SubscriptionId $subId Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subId ``` -Here's a slighly more interesting example... +Here's a slightly more interesting example... If you have multiple subscriptions and need to run various commands on some of them, you can setup a variable for each subscription. Then have a common variable representing the target subscription. The script below will -run commands for the $s2 subscription. However, now if you want to run them for $s3, you just need to edit the "$subId = $s2" line, +run commands for the $s2 subscription. However, if you want to run them for $s3, you just need to edit the "$subId = $s2" line, run that and thereafter run any other code that you wish to run with $s3 as target. ```PowerShell @@ -471,7 +495,7 @@ $s3 = '8feabcde-f012-3456-7890-abcdef012345' $subId = $s2 # Run one or more of the below lines as needed... -Set-AzureRmContext -SubscriptionId $subId +Set-AzContext -SubscriptionId $subId Get-AzSKSubscriptionSecurityStatus -SubscriptionId $subId Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subId ``` @@ -485,7 +509,7 @@ noticed that some examples use single quotes 'my string' while others use double If used in the context of just plain strings with no special characters (like the example above) the two are equivalent. So if all you want to specify is a certain subscriptionId, then using '0e2abcde-f012-3456-7890-abcdef01234f' is the same as "0e2abcde-f012-3456-7890-abcdef01234f". -However, if you want PS to do richer interpretation of stuff inside the quotes then you'd use double quotes. Here are a few examples: +However, if you want PS to do a richer interpretation of what's written inside the quotes then you'd use double quotes. Here are a few examples: ```PowerShell Write-Host "My subscription id is: $subId" #This will replace $subId with the actual value of the variable when printing ``` @@ -541,7 +565,7 @@ operation performed or some expression evaluated for every constituent object in For instance, to print just the location of every resource group in the current subscription, you'd use: ```PowerShell -PS C:\> Get-AzureRmResourceGroup | % {$_.Location} +PS C:\> Get-AzResourceGroup | % {$_.Location} eastus eastus2 eastus @@ -555,12 +579,12 @@ westus This basically tells PS to iterate through the collection returned from the left side of the '|' and, for each object, evaluate the expression within the '{ }'. The key players in the equation are the '|' pipe character, the '%' looping character and the "$\_" inside the '{ }'. -The $\_ basically plays the same role as 'i' in a standard for loop or 'thisObject' in a 'foreach' loop. +The $\_ plays the same role as 'i' in a standard for loop or 'thisObject' in a 'foreach' loop. Here are a few more examples: ```PowerShell # List all resource group names -PS C:\> Get-AzureRmResourceGroup | % {$_.ResourceGroupName} +PS C:\> Get-AzResourceGroup | % {$_.ResourceGroupName} AzSKAPIDev AzSKDemoDataRG AzSKDemoKeyVaultRG @@ -573,7 +597,7 @@ AzSKRG ```PowerShell # List all resource groups in the eastUS2 region -PS C:\> Get-AzureRmResourceGroup | % {if ($_.Location -eq 'eastus2'){Write-Host $_.ResourceGroupName}} +PS C:\> Get-AzResourceGroup | % {if ($_.Location -eq 'eastus2'){Write-Host $_.ResourceGroupName}} AzSKDemoDataRG AzSKDemoKeyVaultRG AzSKTestRG @@ -584,7 +608,7 @@ Wave2RG ```PowerShell # Run a scan command across all subscriptions you have access to -$subscriptions = (Get-AzureRmSubscription) +$subscriptions = (Get-AzSubscription) $subscriptions | % { $subId = $_.Id @@ -597,17 +621,17 @@ $subscriptions | % { If you want to run a loop and evaluate some expression on only those items which meet a particular criteria, you can use the 'where-object' or 'where' or simply the '?' operator to do so. -Example the below command filters for resource groups that have 'rg' anywhere in the name: +For example, the below command filters for resource groups that have 'rg' anywhere in their name: ```PowerShell -Get-AzureRmResourceGroup | ? ResourceGroupName -match 'rg' +Get-AzResourceGroup | ? ResourceGroupName -match 'rg' # Can also be written like this: -Get-AzureRmResourceGroup | ? {$_.ResourceGroupName -match 'rg'} +Get-AzResourceGroup | ? {$_.ResourceGroupName -match 'rg'} ``` [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) ### To '-match' or to '-like'? -PowerShell has extremely powerful string operators. At some point you will look to run some logic based on a string -property of some object. Here there are two operators 'like' and 'match' that can cause confusion (and trouble). +PowerShell has extremely powerful string operators. At some point you will want to run some logic based on a string +property of some object. Here, there are two operators 'like' and 'match' that can cause confusion (and trouble). A basic rule of thumb is that with 'match' you are specifying a regular expression whereas with 'like' you are describing the string just with the help of wildcard character '*'. @@ -643,4 +667,4 @@ A note of caution that the 'contains' operator is supposed to be used for arrays particular string.) [Back to top...](GettingStarted_PowerShellTipsAzSK.md#list-of-tips) - \ No newline at end of file + diff --git a/00b-Getting-Started/GettingStarted_SubscriptionSecurity.md b/00b-Getting-Started/GettingStarted_SubscriptionSecurity.md index f3c07a74..66e955ba 100644 --- a/00b-Getting-Started/GettingStarted_SubscriptionSecurity.md +++ b/00b-Getting-Started/GettingStarted_SubscriptionSecurity.md @@ -1,9 +1,14 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. ## Scan your Azure Subscription for security vulnerabilities ###### :clock10: 30 minutes to complete The Subscription Security health check features in AzSK contains a set of scripts that examines a subscription and flags off security issues, misconfigurations or obsolete artifacts/settings which can put your subscription at higher risk. -This package adds-on to the exiting Azure capabilities like Security Center, IAM, etc. and extends it further to check for the presence for non-tenant accounts, SPN with higher priviliges, alerting configuration, etc. +This package adds-on to the exiting Azure capabilities like Security Center, IAM, etc. and extends it further to check for the presence for non-tenant accounts, SPN with higher privileges, alerting configuration, etc. -> Note: Ensure that you already have the latest version of AzSK installed on your machine. If not, please follow instruction [here.](../00a-Setup/Readme.md) +> Note: Ensure that you already have the latest version of AzSK installed on your machine. If not, please follow instruction [here](../00a-Setup/Readme.md). **Step 1**: In the PowerShell ISE, run the below command after replacing ` with your Azure SubscriptionId ```PowerShell @@ -26,12 +31,12 @@ Once all rules have been processed execution completes and the output folder is ![00_Security_Status_OP_Folder](../Images/00_Security_Status_OP_Folder.PNG) -**Understanding the ouputs** +**Understanding the outputs** As the rules are checked, in the background AzSK collates the following: - summary information of the control evaluation (pass/fail) status in a CSV file, - detailed control evaluation log in a LOG file and -- a few other anciliary files for additional support +- a few other ancillary files for additional support > **Note:** The overall layout and files in the output folder are also described in the **ReadMe.txt** file present in the root output folder (the one that is opened automatically). diff --git a/00b-Getting-Started/Readme.md b/00b-Getting-Started/Readme.md index f8a45d6f..ab135cac 100644 --- a/00b-Getting-Started/Readme.md +++ b/00b-Getting-Started/Readme.md @@ -1,3 +1,8 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # Getting started with the Secure DevOps Kit for Azure! If you have just installed the Secure DevOps Kit for Azure (a.k.a. AzSK) and are not familiar with @@ -25,45 +30,84 @@ in the table below: [Secure Development](../02-Secure-Development/Readme.md) |
  • Security Verification Tests (SVTs)
  • Security IntelliSense VS Editor Extension
[Security in CICD](../03-Security-In-CICD/Readme.md) |
  • AzSK-SVTs VSTS extension for injecting security tests in a CICD pipeline
[Continuous Assurance](../04-Continous-Assurance/Readme.md) |
  • Security scanning of Azure subscription and applications via automation runbooks
-[Alerting & Monitoring](../05-Alerting-and-Monitoring/Readme.md) |
  • Leveraging OMS towards:
    • Single pane view of security across dev ops stages
    • Security alerts based on various search conditions.
+[Alerting & Monitoring](../05-Alerting-and-Monitoring/Readme.md) |
  • Leveraging Log Analytics towards:
    • Single pane view of security across dev ops stages
    • Security alerts based on various search conditions.
[Cloud Risk Governance](../06-Security-Telemetry/Readme.md) |
  • Support for control state attestation and security governance dashboards.
-## List Of AzSK commands +## Complete list of AzSK commands + +> **Note**: Most of the AzSK cmdlets support 3 letter acronyms (e.g., GRS, ICA, UCA, etc.). You can invoke cmdlets using these *after* AzSK has been imported in the session. So, to use any of these aliases, make sure you run 'ipmo AzSK' as the first thing in a new PS/ISE console window ('ipmo' itself is an alias for 'import-module'). Apart from cmdlets, parameters also have associated aliases. Those are documented in the individual cmdlet documentation. + +> For a quick reference on aliases, you can run 'get-alias | findstr -i AzSk' within a PS/ISE console after running 'ipmo AzSK'. + -|Command|What it does| Role/Permission| +| Command (alias) | What it does | Required Permission | |----|----|-----| +|Clear-AzSKSessionState (CSS)|Command to clear AzSK session object|NA| |Get-AzSKAzureServicesSecurityStatus (GRS)|Scans a set of RGs (or the entire subscription)|Reader on subscription or respective RGs| |Get-AzSKContinuousAssurance (GCA)|Validates the status of Continuous Assurance automation account including the condition of various artifacts such as storage account, schedules, runbooks, SPN/connection, required modules, etc.|Reader on subscription.| -|Get-AzSKControlsStatus (GCS)|Single cmdlet that combines Get-AzSKSubscriptionSecurityStatus, Get-AzSKAzureServicesSecurityStatus|Union of permissions.| +|Get-AzSKControlsStatus (GACS)|Single cmdlet that combines Get-AzSKSubscriptionSecurityStatus, Get-AzSKAzureServicesSecurityStatus|Union of permissions.| |Get-AzSKExpressRouteNetworkSecurityStatus (GES)|Validate secure configuration of ER-connected vNets. Also validates custom/supporting protections |Reader on ERNetwork, Reader on sub.| |Get-AzSKSubscriptionSecurityStatus (GSS)|Scans an Azure subscription for security best practices and configuration baselines for things such as alerts, ARM policy, RBAC, ASC, etc.|Reader on subscription| -|Get-AzSKSupportedResourceTypes|Lists the currently supported Azure service types in AzSK. Basically, all resources in this list have SVTs available and these SVTs will be invoked whenever Get-AzSKAzureServicesSecurityStatus is run.|NA.| -|Get-AzSKInfo|This command would help users to get details of various components of AzSK. |Reader on subscription, Contributor on AzSKRG| +|Get-AzSKSupportedResourceTypes (GSRT)|Lists the currently supported Azure service types in AzSK. Basically, all resources in this list have SVTs available and these SVTs will be invoked whenever Get-AzSKAzureServicesSecurityStatus is run.|NA.| +|Get-AzSKInfo (GAI)|This command would help users to get details of various components of AzSK. |Reader on subscription, Contributor on AzSKRG| |Install-AzSKContinuousAssurance (ICA)|Sets up continuous assurance for a subscription. This creates various artifacts such as resource group, storage account and automation account| Owner on subscription.| -|Install-AzSKOMSSolution (IOM)|Creates and deploys an OMS view in a subscription that has an OMS workspace. The OMS view provides visibility to application state across dev ops stages. It also creates alerts, common search queries, etc. |Reader on subscription.| +|Install-AzSKMonitoringSolution (IMS)|Creates and deploys a Log Analytics view in a subscription that has a Log Analytics workspace. The Log Analytics view provides visibility to application state across dev ops stages. It also creates alerts, common search queries, etc. |Reader on subscription.| |Remove-AzSKAlerts (RAL)|Removes the alerts configured by AzSK.|Owner on subscription.| |Remove-AzSKARMPolicies (RAP)|Removes the ARM policy configured by AzSK.|Owner on subscription.| |Remove-AzSKContinuousAssurance (RCA)|Removes the AzSK CA setup (including, optionally, the container being used for storing reports).|Reader on subscription.| |Remove-AzSKSubscriptionRBAC (RRB)|Removes the RBAC setup by AzSK. By default "mandatory" central accounts are not removed and "deprecated" accounts are always removed.|Owner on subscription.| |Remove-AzSKSubscriptionSecurity (RSS)|Removes the configuration done via Set-AzSKSubscriptionSecurity. It invokes the individual remove commands for RBAC, ARM policy, Alerts and ASC.|Owner on subscription.| -|Repair-AzSKAzureServicesSecurity (FRS)|Fixes the security controls for various Azure resources using the automated fixing scripts generated by running the AzSK scan command "Get-AzSKAzureServicesSecurityStatus" with the '-GenerateFixScript' flag.|Contributor on subscription or respective RGs | -|Repair-AzSKSubscriptionSecurity (FSS)|Fixes the subscription security related controls using the automated fixing scripts generated by running the AzSK scan command "Get-AzSKSubscriptionSecurityStatus" with the '-GenerateFixScript' flag.|Contributor on subscription| -|Set-AzSKAlerts (SAL)|Sets up activity alerts for the subscription. Includes alerts for subscription and resource specific activities. Alerts can be scopes to subscription or RGs.
This is internally called by Set-AzSKSubscriptionSecurity.|Owner on subscription. +|Repair-AzSKAzureServicesSecurity (RRS)|Fixes the security controls for various Azure resources using the automated fixing scripts generated by running the AzSK scan command "Get-AzSKAzureServicesSecurityStatus" with the '-GenerateFixScript' flag.|Contributor on subscription or respective RGs | +|Repair-AzSKSubscriptionSecurity (RASS)|Fixes the subscription security related controls using the automated fixing scripts generated by running the AzSK scan command "Get-AzSKSubscriptionSecurityStatus" with the '-GenerateFixScript' flag.|Contributor on subscription| +|Set-AzSKAlerts (SAA)|Sets up activity alerts for the subscription. Includes alerts for subscription and resource specific activities. Alerts can be scopes to subscription or RGs.
This is internally called by Set-AzSKSubscriptionSecurity.|Owner on subscription. |Set-AzSKARMPolicies (SAP)|Sets up a core set of ARM policies in a subscription.
This is internally called by Set-AzSKSubscriptionSecurity.|Owner on subscription.| |Set-AzSKAzureSecurityCenterPolicies (SSC)|Sets up ASC policies and security points of contact.
This is internally called by Set-AzSKSubscriptionSecurity.|Reader on subscription.| -|Set-AzSKEventHubSettings |Configures AzSK to send scan results to the provided EventHub. Currently available only in 'ad hoc' or 'SDL' mode.|NA| -|Set-AzSKLocalControlTelemetrySettings|The command configures the AzSK toolkit to send data to the given Applications Insights account from user's machine.|NA| -|Set-AzSKOMSSettings|Configures AzSK to send scan results to the provided OMS workspace. Events can be sent to OMS from 'ad hoc'/SDL mode (via this configuration) or from CICD by specifying OMS settings in a variable or from CA by specifying OMS settings in the CA installation command.|Reader on subscription.| -|Set-AzSKPolicySettings|Configures the server URL that is used by AzSK to download controls and config JSON. If this is not called, AzSK runs in an 'org-neutral' mode using a generic policy. Once this command is called, AzSK gets provisioned with the URL of a server/CDN where it can download control/config JSON from.|Reader on subscription.| +|Set-AzSKEventHubSettings (SEHS)|Configures AzSK to send scan results to the provided EventHub. Currently available only in 'ad hoc' or 'SDL' mode.|NA| +|Set-AzSKMonitoringSettings (SMS)|Configures AzSK to send scan results to the provided Log Analytics workspace. Events can be sent to Log Analytics from 'ad hoc'/SDL mode (via this configuration) or from CICD by specifying Log Analytics settings in a variable or from CA by specifying Log Analytics settings in the CA installation command.|Reader on subscription.| +|Set-AzSKPolicySettings (SPS)|Configures the server URL that is used by AzSK to download controls and config JSON. If this is not called, AzSK runs in an 'org-neutral' mode using a generic policy. Once this command is called, AzSK gets provisioned with the URL of a server/CDN where it can download control/config JSON from.|Reader on subscription.| |Set-AzSKSubscriptionRBAC (SRB)|Sets up RBAC for a subscription. Configures "mandatory" accounts by default and function/scenario specific accounts if additional "tags" are provided.|Owner on subscription.| |Set-AzSKSubscriptionSecurity (SSS)|Master command that takes combined inputs and invokes the individual setup commands for RBAC, ARM policy, Alerts and ASC.|Owner on subscription.| -|Set-AzSKUsageTelemetryLevel|Command to switch the default TM level for AzSK. The generic version of AzSK comes with 'Anonymous' level telemetry. The other levels supported is 'None'. |NA| -|Set-AzSKLocalAIOrgTelemetrySettings|Command to set local control telemetry settings. |NA| -|Set-AzSKWebhookSettings|Configures AzSK to send scan results to the provided webhook. Currently available only in 'ad hoc' or 'SDL' mode.
This capability can be used to receive AzSK scan results in arbitrary downstream systems. (E.g., Splunk)|NA| -|Set-AzSKUserPreference|This command can be used to set user preferences (e.g.: output folder path) for AzSK commands.|NA| -|Install-AzSKOrganizationPolicy|This command is intended to be used by central Organization team to setup Organization specific policies. |Contributor on subscription| -|Update-AzSKContinuousAssurance (UCA)|Updates various parameters that were used when CA was originally setup. This command can be used to change things like target resource groups that were scanned, OMS workspaceID and sharedKey, run as account used by CA for scanning, update/renew certificate credential as run as account. | Owner on subscription.| +|Set-AzSKUsageTelemetryLevel (SUTL)|Command to switch the default TM level for AzSK. The generic version of AzSK comes with 'Anonymous' level telemetry. The other levels supported is 'None'. |NA| +|Set-AzSKLocalAIOrgTelemetrySettings (SLOTS)|Command to set local control telemetry settings. |NA| +|Set-AzSKWebhookSettings (SWHS)|Configures AzSK to send scan results to the provided webhook. Currently available only in 'ad hoc' or 'SDL' mode.
This capability can be used to receive AzSK scan results in arbitrary downstream systems. (E.g., Splunk)|NA| +|Set-AzSKUserPreference (SUP)|This command is useful to set user preferences for AzSK commands. E.g. 1. Run 'Set-AzSKUserPreference -OutputFolderPath ' to override default path 2. Rn 'Set-AzSKUserPreference -DoNotOpenOutputFolder' to not open output folder by default.|NA| +|Install-AzSKOrganizationPolicy (IOP)|This command is intended to be used by central Organization team to setup Organization specific policies. |Contributor on subscription| +|Update-AzSKContinuousAssurance (UCA)|Updates various parameters that were used when CA was originally setup. This command can be used to change things like target resource groups that were scanned, Log Analytics workspaceID and sharedKey, run as account used by CA for scanning, update/renew certificate credential as run as account. | Owner on subscription.| |Update-AzSKSubscriptionSecurity (USS)|This command can be used to update various security baseline elements and bring your subscription up to speed from a baseline policy compliance of subscription security controls. It updates one or more of the following elements after checking the ones that are out of date - alerts, Security Center, ARM policy, RBAC (mandatory accounts and deprecated accounts), continuous assurance runbook, etc.|Owner on subscription.| -|Update-AzSKOrganizationPolicy|This command is intended to be used by central Organization team to update Organization specific policies. |Contributor on subscription| +|Update-AzSKOrganizationPolicy (UOP)|This command is intended to be used by central Organization team to update Organization specific policies. |Contributor on subscription| + + +## List of commonly used parameters + +| Parameter (alias) | +|-------------------| +|SubscriptionId (s,sid)| +|ResourceGroupNames (rgns)| +|ResourceType (rt)| +|ResourceTypeName (rtn)| +|ResourceNames (rns)| +|ControlIds (cids)| +|ControlsToAttest (cta)| +|UseBaselineControls (ubc)| + +## Some commonly used commands +```PowerShell +grs -s -rgns -rns -ubc +``` +```PowerShell +gss -s +``` +```PowerShell +ica -hsid -rgns -owid -okey +``` +```PowerShell +uca -hsid +``` +```PowerShell +gacs -s -rgns -rns -cids +``` +```PowerShell +uss -s -f -dnof +``` diff --git a/00c-Addressing-Control-Failures/Readme.md b/00c-Addressing-Control-Failures/Readme.md index 153251e2..d1a96972 100644 --- a/00c-Addressing-Control-Failures/Readme.md +++ b/00c-Addressing-Control-Failures/Readme.md @@ -1,3 +1,8 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # Addressing Control Failures ### Contents @@ -18,6 +23,10 @@ - [Permissions required for attesting controls](Readme.md#permissions-required-for-attesting-controls) - [Attestation expiry](Readme.md#attestation-expiry) - [Bulk attestation](Readme.md#bulk-attestation) + + +### [FAQs](Readme.md#faqs) + ---------------------------------------------------------------- # Introduction @@ -50,14 +59,14 @@ You can use the 'DetailedLogFile' field to locate the LOG file where control eva is written by AzSK. (This file can be different for different resources/resource groups.) See the image below: - ![CSV File](../Images/00_ACF_Basics_CSV.png) + ![CSV File](../Images/00_ACF_Basics_CSV.PNG) For some controls, AzSK can automatically generate scripts that can be run to address the control failures. This can be done using the '-GenerateFixScript' flag in the scan commands. Whether AzSK has support for auto-generating the fix script for a control is represented by the 'SupportsAutoFix' column for that control. Also, sometimes, you will need to complement or override AzSK's control evaluation result with additional -contextual knowledge. This is called 'Control Attestation' and is supported by the '-AttestControls' flag in the scan commands. +contextual knowledge. This is called 'Control Attestation' and is supported by the '-ControlsToAttest' flag in the scan commands. The rest of this section explains these two capabilities in detail. @@ -103,7 +112,7 @@ The contents of the 'FixControlScripts' folder are organized as under: - *\RunFixScript.ps1* - The file which starts implementing the recommendations. The file typically contains repair command which uses the files from current folder. - *\FixControlConfig.json* - The file contains the configuration of controls along with mandatory/optional parameters which are required for implementing the fix for control. - *\Services* - The folder contains the PowerShell files which are used to implement the fix for control. - - *\\\.ps1* - The file contains PowerShell code to implement the fix for control. The file can be referred for review. + - *\\\.ps1* - The file contains PowerShell code to implement the fix for control. The file can be referred for review. - *\FixControlConfig-\.json* - This file is generated when repair command is run. The file contains the input values provided by user while running the repair command. The file can be referred for review. [Back to top...](Readme.md#contents) @@ -121,8 +130,8 @@ This command remediates the subscription security related controls using the aut |Parameter|Name|Description| |----|----|----| -|ParameterFilePath |The full file path to 'FixControlConfig.json' (by default generated in sub-folder 'FixControlScripts' of the AzSK scan command output folder).|Mandatory| -|ControlIds|The list of control ids for which fixes should be applied.|Optional| +|ParameterFilePath |Full file path to 'FixControlConfig.json' (by default generated in sub-folder 'FixControlScripts' of the AzSK scan command output folder).|Mandatory| +|ControlIds|List of control ids for which fixes should be applied.|Optional| |Force|Switch to bypass user consent of modifying Azure resources|Optional| For example, @@ -134,12 +143,12 @@ This command remediates security controls for various Azure resources using the |Parameter|Name|Description| |----|----|----| -|ParameterFilePath |The full file path of 'FixControlConfig.json' (by default generated in sub-folder 'FixControlScripts' of the AzSK scan command output folder). |Mandatory | -|ResourceGroupNames |The list of resource groups for which fixes should be applied. |Optional | -|ResourceTypes |The list of resource types for which fixes should be applied. E.g., Microsoft.Sql/servers. |Optional | -|ResourceTypeNames |The list of resource type names for which fixes should be applied. E.g., SQLDatabase. |Optional | -|ResourceNames |The list of resources for which fixes should be applied. |Optional | -|ControlIds |The list of control ids for which fixes should be applied. |Optional | +|ParameterFilePath |Full file path of 'FixControlConfig.json' (by default generated in sub-folder 'FixControlScripts' of the AzSK scan command output folder). |Mandatory | +|ResourceGroupNames |List of resource groups for which fixes should be applied. |Optional | +|ResourceTypes |List of resource types for which fixes should be applied. E.g., Microsoft.Sql/servers. |Optional | +|ResourceTypeNames |List of resource type names for which fixes should be applied. E.g., SQLDatabase. |Optional | +|ResourceNames |List of resources for which fixes should be applied. |Optional | +|ControlIds |List of control ids for which fixes should be applied. |Optional | |Force |Switch to bypass user consent prompts when modifying Azure resources |Optional | For example, @@ -169,7 +178,7 @@ be combined with the user's input in order to determine the overall or effective and, after the process is performed once, AzSK remembers it and generates an effective control result for subsequent control scans _until_ there is a state change. -The attestation feature is implemented via a new switch called *AttestControls* which can be specified in any of the standard security scan cmdlets +The attestation feature is implemented via a new switch called *ControlsToAttest* which can be specified in any of the standard security scan cmdlets of the AzSK. When this switch is specified, the AzSK first performs a scan of the target resource(s) like it is business as usual and, once the scan is complete, it enters a special interactive 'attest mode' where it walks through each resource and relevant attestable controls and captures inputs from the user and records them in the subscription (along with details about the person who attested, the time, etc.). @@ -185,14 +194,16 @@ the permissions required section below. [Back to top...](Readme.md#contents) ### Starting attestation -The AzSK subscription and services scan cmdlets now support a new switch called *AttestControls*. When this switch is specified, +The AzSK subscription and services scan cmdlets now support a new switch called *ControlsToAttest*. When this switch is specified, AzSK enters 'attest' mode immediately after a scan is completed. This ensures that attestation is done on the basis of the most current control statuses. All controls that have a technical evaluation status of anything other than 'Passed' (i.e., 'Verify' or 'Failed' or 'Manual' or 'Error') are considered valid targets for attestation. -To manage attestation flow effectively, 4 options are provided for the *AttestControls* switch to specify which subset of controls to target for attestation. These are described below: +> **Note**: Some controls are very crucial from security stand point and hence AzSK does not support attesting them. + +To manage attestation flow effectively, 4 options are provided for the *ControlsToAttest* switch to specify which subset of controls to target for attestation. These are described below: |Attestation Option|Description| |------------------|-----------| @@ -204,7 +215,7 @@ To manage attestation flow effectively, 4 options are provided for the *AttestCo For example, to attest controls corresponding to a subscription security scan, run the command below: ```PowerShell $subscriptionId = -Get-AzSKSubscriptionSecurityStatus -SubscriptionId $subscriptionId -AttestControls NotAttested -DoNotOpenOutputFolder +Get-AzSKSubscriptionSecurityStatus -SubscriptionId $subscriptionId -ControlsToAttest NotAttested -DoNotOpenOutputFolder ``` As shown in the images, the command enters 'attest' mode after completing a scan and does the following: @@ -212,15 +223,19 @@ As shown in the images, the command enters 'attest' mode after completing a scan 2. The user gets to choose whether they want to attest the control 3. If the user chooses to attest, attestation details (attest status, justification, etc.) are captured 4. This is repeated for all attestable controls and each resource. +5. After attestation workflow is completed, another scan is triggered for controls attested within the last 24 hrs so that the backend will get the latest control status. Sample attestation workflow in progress: - ![02_SVT_Attest_1](../Images/02_SVT_Attest_1.png) + ![02_SVT_Attest_1](../Images/02_SVT_Attest_1.PNG) Sample summary of attestation after workflow is completed: - ![02_SVT_Attest_2](../Images/02_SVT_Attest_2.png) + ![02_SVT_Attest_2](../Images/02_SVT_Attest_2.PNG) -Attestation details corresponding to each control (e.g., justification, user name, etc.) are also captured in the CSV file as shown below: - ![02_SVT_Attest_3](../Images/02_SVT_Attest_3.png) + Sample summary of scan of attested controls: + ![02_SVT_Attest_4](../Images/02_SVT_Attest_4.PNG) + +Attestation details corresponding to each control (e.g., justification, user name, etc.) are also captured in the CSV file in next scan as shown below: + ![02_SVT_Attest_3](../Images/02_SVT_Attest_3.PNG) The attestation process for application resources is similar to that for subscriptions. For example, the command below shows how to trigger attestation for a specific resource in an RG: @@ -232,7 +247,7 @@ $resourceName = Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` -ResourceGroupNames $resourceGroupName ` -ResourceName $resourceName ` - -AttestControls NotAttested ` + -ControlsToAttest NotAttested ` -DoNotOpenOutputFolder ``` If, for any reason, the attestations of previously attested controls need to be revisited, it can be done by simply changing the 'NotAttested' flag in the commands above with 'AlreadyAttested'. @@ -247,11 +262,14 @@ fixing the issue for the time being): |Attestation Status | Description| |---|---| -|None | There is no attestation done for a given control. User can select this option duriung the workflow to skip the attestation| -|NotAnIssue | User has verified the control data and attesting it as not a issue with proper justification| +|None | There is no attestation done for a given control. User can select this option during the workflow to skip the attestation| +|NotAnIssue | User has verified the control data and attesting it as not an issue with proper justification to represent situations where the control is implemented in another way, so the finding does not apply. | |WillNotFix | User has verified the control data and attesting it as not fixed with proper justification| |WillFixLater | User has verified the control data and attesting it as not fixed with proper justification stating the future fix plan| +|**NotApplicable | User has verified the control data and attesting it as not applicable for the given design/context with proper justification. | +|**StateConfirmed | User has verified the control data and attesting it as state confirmed to represent that the control state is correct/appropriate with proper justification. | + > ** These are special attestation status which are supported only in selected controls. The following table shows the complete 'state machine' that is used by AzSK to support control attestation. The columns are described as under: @@ -265,21 +283,29 @@ The columns are described as under: |---|---|---|---|---|---| |Passed |None |Passed |No | -NA- |No need for attestation. Control has passed outright!| |Verify |None |Verify |No | -NA- |User has to ratify based on manual examination of AzSK evaluation log. E.g., SQL DB firewall IPs list.| -|Verify |NotAnIssue |Passed |Yes | 90 |User has ratified in the past. E.g., SQL firewall IPs scenario, where all are IPs are legitimate.| -|Verify |WillNotFix |Exception |Yes | Based on the control severity table below|Valid security issue but a fix cannot be implemented immediately. E.g., A 'deprecated' account was found in the subscription. However, the user wants to check any dependecies before removal.| -|Verify |WillFixLater |Remediate |Yes| Based on the control severity table below|Valid security issue but a fix cannot be implemented immediately. E.g., A 'deprecated' account was found in the subscription. However, the user wants to check any dependecies before removal.| +|Verify |NotAnIssue |Passed |Yes | 90 |User has to ratify based manual examination that finding does not apply as the control has been implemented in another way. For example, AAD authentication for App Service was implemented through code. | +|Verify |WillNotFix |Exception |Yes | Based on the control severity table below|Valid security issue but a fix cannot be implemented immediately. E.g., A 'deprecated' account was found in the subscription. However, the user wants to check any dependencies before removal.| +|Verify |WillFixLater |Remediate |Yes| Based on the control severity table below|Valid security issue but a fix cannot be implemented immediately. E.g., A 'deprecated' account was found in the subscription. However, the user wants to check any dependencies before removal.| +|Verify |NotApplicable |Passed |Yes| 90 |User has to ratify based on manual examination that the finding is not applicable for given design/context. E.g., Runbook does not contain any hard-coded secure information. | +|Verify |StateConfirmed |Passed |Yes| Based on the control severity table below|User has to ratify based on manual examination that the control state is correct/appropriate. E.g., SQL firewall IPs scenario, where all IPs are legitimate.| |Failed |None |Failed |No | -NA- | Control has failed but has not been attested. Perhaps a fix is in the works...|   -|Failed |NotAnIssue |Passed |Yes | 90 |Control has failed but the issue is benign in a given context business. E.g., Failover instance for a non BC-DR critical service| -|Failed |WillNotFix |Exception |Yes | Based on the control severity table below| Control has failed. The issue is not benign but the user has some other constraint and cannot fix it. E.g., Need an SPN to be in Owner role at subscription scope.| -|Failed |WillFixLater |Remediate |Yes | Based on the control severity table below| Control has failed. The issue is not benign but the user wishes to defer fixing it for later. E.g., AAD is not enabled for Azure SQL DB.| +|Failed |NotAnIssue |Passed |Yes | 90 |Control has failed. However, the finding does not apply as the control has been implemented in another way. For example, AAD authentication for App Service was implemented through code.| +|Failed |WillNotFix |Exception |Yes | Based on the control severity table below| Control has failed. The issue is not benign, but the user has some other constraint and cannot fix it. E.g., Need an SPN to be in Owner role at subscription scope.| +|Failed |WillFixLater |Remediate |Yes | Based on the control severity table below| Control has failed. The issue is not benign, but the user wishes to defer fixing it for later. E.g., AAD is not enabled for Azure SQL DB.| +|Failed |NotApplicable |Passed |Yes| 90 |Control has failed. However, user confirms based on manual examination that the finding is not applicable for given design/context.| +|Failed |StateConfirmed |Passed |Yes| Based on the control severity table below|Control has failed. However, user confirms based on manual examination that the control state is correct/appropriate. | |Error |None |Error |No | -NA- | There was an error during evaluation. Manual verification is needed and is still pending.| -|Error |NotAnIssue |Passed |Yes | 90| There was an error during evaluation. However, control has been manually verified by the user.| +|Error |NotAnIssue |Passed |Yes | 90| There was an error during evaluation. Manual verification by user indicates that the finding does not apply as the control has been implemented in another way.| |Error |WillNotFix |Exception |Yes | Based on the control severity table below| There was an error during evaluation. Manually verification by the user indicates a valid security issue.| |Error |WillFixLater |Remediate |Yes | Based on the control severity table below| There was an error during evaluation. Manually verification by the user indicates a valid security issue.| +|Error |NotApplicable |Passed |Yes| 90 |There was an error during evaluation. However, user confirms based on manual examination that the finding is not applicable for given design/context.| +|Error |StateConfirmed |Passed |Yes| Based on the control severity table below|There was an error during evaluation. However, user confirms based on manual examination that the control state is correct/appropriate.| |Manual |None |Manual |No | -NA-| The control is not automated and has to be manually verified. Verification is still pending.|  -|Manual |NotAnIssue |Passed |Yes | 90| The control is not automated and has to be manually verified. User has verified that there's no security concern.| +|Manual |NotAnIssue |Passed |Yes | 90| The control is not automated and has to be manually verified. User has reviewed the security concern and implemented the fix in another way.| |Manual |WillNotFix |Exception |Yes | Based on the control severity table below| The control is not automated and has to be manually verified. User has reviewed and found a security issue to be fixed.| |Manual |WillFixLater |Remediate |Yes | Based on the control severity table below| The control is not automated and has to be manually verified. User has reviewed and found a security issue to be fixed.| +|Manual |NotApplicable |Passed |Yes| 90 |The control is not automated and has to be manually verified. User confirms based on manual examination that the finding for given design/context is not applicable. | +|Manual |StateConfirmed |Passed |Yes| Based on the control severity table below| The control is not automated and has to be manually verified. User has verified that there's no security concern.| -NA- => Not Applicable @@ -299,7 +325,7 @@ The following table describes the possible effective control evaluation results |Control Scan Result| Description| |---|---| |Passed |Fully automated control. Azure resource/subscription configuration meeting the AzSK control requirement| -|Verfiy |Semi-automated control. It would emit the required data in the log files which can be validated by the user/auditor.e.g. SQL DB IP ranges| +|Verify |Semi-automated control. It would emit the required data in the log files which can be validated by the user/auditor. e.g. SQL DB IP ranges| |Failed |Fully automated control. Azure resource/subscription configuration not meeting AzSK control requirement| |Error |Automated control. Currently failing due to some exception. User needs to validate manually| |Manual |No automation as of now. User needs to validate manually| @@ -317,13 +343,13 @@ If this RG is not present (as is possible when none of the scenarios that intern [Back to top...](Readme.md#contents) ### Attestation expiry: -All the control attestations done through devops kit is set with a default expiry. This would force teams to revisit the control attestation at regular intervals. +All the control attestations done through AzSK is set with a default expiry. This would force teams to revisit the control attestation at regular intervals. Expiry of an attestation is determined through different parameters like control severity, attestation status etc. There are two simple rules for determining the attestation expiry. Those are: Any control with evaluation result as not passed, - 1. and attested as 'NotAnIssue', such controls would expire in 90 days. - 2. and attested as 'WillFixLater' or 'WillNotFix', such controls would expire based on the control severity table below. + 1. and attested as 'NotAnIssue' or 'NotApplicable', such controls would expire in 90 days. + 2. and attested as 'WillFixLater' or 'WillNotFix' or 'StateConfirmed', such controls would expire based on the control severity table below. |ControlSeverity| ExpiryInDays| |----|---| @@ -332,8 +358,15 @@ Any control with evaluation result as not passed, |Medium| 60| |Low| 90| -The detailed matrix of attestation details and its expiry can be found under [this](Readme.md#how-AzSK-determines-the-effective-control-result) section. - +The detailed matrix of attestation details and its expiry can be found under [this](Readme.md#how-azsk-determines-the-effective-control-result) section. Attestation expiry date is also emitted in CSV scan result as shown in [this](../Images/02_SVT_Attest_3.PNG) image. + +> **Note**: +> * All the controls are subjected to an initial grace period from the first scanned date. On expiry of grace period for a control, +> 1. 'WillFixLater' option will be disabled for further attestation. +> 2. if the control was attested as 'WillFixLater', then attestation will expire. +> User will then have the option to either fix the control or use other available attestation states with proper justification. +> +>* Attestation may also expire before actual expiry in cases when the attested state for the control doesn't match with current control state. [Back to top...](Readme.md#contents) ### Bulk attestation @@ -343,11 +376,11 @@ you may have 35 storage accounts for which you need to perform attestation for o a time can be inefficient - especially if the reason for attesting the control is the same across all those resource instances. The bulk attestation feature helps by empowering subscription/security owners to provide a common justification for a set of resources all of which have a specific (single) controlId that requires attestation. This essentially 'automates' attestation by using -a slightly different combination of parameters alongside '-AttestControls'. +a slightly different combination of parameters alongside '-ControlsToAttest'. ```PowerShell -$subscriptionId = 'sub_id_here' -$resourceGroupNames = 'Comma-separated list of RGs' +$subscriptionId = 'Your subscription Id' +$resourceGroupNames = 'Comma-separated list of resource groups' $resourceNames = 'Comma-separated list of resources' $bulkAttestControlId = 'AzSK ControlId string' # You can get this from the CSV file, first column. $justificationText = 'Rationale behind your choice of AttestationStatus here...' @@ -355,7 +388,7 @@ $justificationText = 'Rationale behind your choice of AttestationStatus here...' Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` -ResourceGroupNames $resourceGroupNames ` -ResourceNames $resourceNames ` - -AttestControls NotAttested ` + -ControlsToAttest NotAttested ` -BulkAttestControlId $bulkAttestControlId ` # ControlId to be attested -AttestationStatus ` # Attestation choice/input, use one of these. -JustificationText $justificationText # Additional (text) justification @@ -365,8 +398,8 @@ Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` |Parameter Name| Description| |---|---| -|BulkAttestControlId | The controlId to bulk-attest. Bulk attest mode supports only one controlId at a time.| -|AttestControls | See table in the [Starting Attestation](Readme.md#starting-attestatio) section. | +|BulkAttestControlId |ControlId to bulk-attest. Bulk attest mode supports only one controlId at a time.| +|ControlsToAttest | See table in the [Starting Attestation](Readme.md#starting-attestation) section. | |AttestationStatus | Attester must select one of the attestation reasons (NotAnIssue, WillNotFix, WillFixLater)| |JustificationText | Attester must provide an apt justification with proper business reason.| @@ -390,7 +423,7 @@ $justificationText = 'AAD authentication has been enabled through code and has b Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` -ResourceTypeName AppService ` -ResourceNames $resourceName ` - -AttestControls NotAttested ` + -ControlsToAttest NotAttested ` -BulkAttestControlId $bulkAttestControlId ` -AttestationStatus NotAnIssue ` -JustificationText $justificationText @@ -410,10 +443,10 @@ Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` ``` ###### Scenario 2: ###### -An application uses many Storage Accounts, of which a subset are used only to store web site performance logs. +An application uses many Storage Accounts, of which a subset is used only to store web site performance logs. Because these logs aren't critical business data, the business does not want to incur the expense of geo-redundant storage for the storage accounts holding them. All other storage accounts, however, store critical business data which business absolutely -cannot afford to lose in the event of regional disasters. Thus we have a situation where an AzSK control (in this case +cannot afford to lose in the event of regional disasters. Thus, we have a situation where an AzSK control (in this case the GRS setting for Storage Accounts) must pass for a subset of resources while it need to be 'attested' for the remainder. @@ -429,7 +462,7 @@ Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` -ResourceTypeName Storage ` -ResourceName $resourceName ` -BulkAttestControlId $bulkAttestControlId ` - -AttestControls NotAttested ` + -ControlsToAttest NotAttested ` -AttestationStatus NotAnIssue ` -JustificationText $justificationText ``` @@ -451,7 +484,7 @@ Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` **Bulk clearing past attestation:** The bulk attestation feature can also be used for situations where a user wants to clear the attestation for -multiple resources in bulk, for a spcified controlId. This can be achieved by running the command below: +multiple resources in bulk, for a specified controlId. This can be achieved by running the command below: ```PowerShell $subscriptionId = @@ -460,8 +493,197 @@ $resourceName = $bulkAttestControlId = $justificationText = Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId -ResourceGroupNames $resourceGroupName -ResourceName $resourceName ` - -BulkAttestControlId $bulkAttestControlId -AttestControls AlreadyAttested -BulkClear + -BulkAttestControlId $bulkAttestControlId -ControlsToAttest AlreadyAttested -BulkClear ``` -> **Note**: Usage of BulkClear with 'NotAttested' Option of AttestControls param, would result in failure. +> **Note**: Usage of BulkClear with 'NotAttested' Option of ControlsToAttest param, would result in failure. + +### FAQs + +##### Can fixing an AzSK control impact my application? + +Most of the AzSK recommendations are generic and are based on security standards and best practices that are widely applicable when processing sensitive data. However, just like any other configuration change, a change to security configuration should be treated with care especially in production environments. In other words, do exercise due diligence and perform good testing (to assess impact on functionality, performance and cost) and follow the required change management discipline expected from engineering teams in your org before making changes in the context of business critical workloads. It is also useful to review any changes with the application architect/design team. This helps ensure a more comprehensive impact assessment. + +As examples, we have had a few cases where teams directly made changes to production and realized that it broke their business scenarios. E.g. there were a couple of applications where internal components in the app were using a hard-coded 'non-HTTPS' string to access a Web API also within the app. As a result, when the Web API was switched to use HTTPS-only, the application workflow started breaking. :-( + +Clearly, these changes themselves were required (per security policy/standards) and were the right thing for securing the enterprise data these applications were handling. Yet, because the applications were not themselves designed to be able to handle the change it led to production impact. (These are also important lessons for all of us on the value of embedding security from the very start in every stage of dev ops...right from subscription provisioning through prototyping, development, deployment (CICD) and operations.) +On a related note, every control in the AzSK may not be applicable to every scenario. Some controls are, by nature, contextual. Others are best practices that are 'good to have' but not a 'must'. In such cases, the control recommendations do provide indications (using wording such as 'where possible' or 'where applicable'). For example, if a backend store is accessed from a multitude of client devices practically from anywhere then an IP-based restriction may not be practical to impose on the data store. However, in another application, one may have a scenario where the backend store is accessed from a controlled pool of middle tier servers (only). In such a case, an IP-based restriction is practical and can add an extra layer of security if the data is highly sensitive in nature. + +#### What permission should I have to perform attestation in AzSK? + +Control attestation is a privileged operation. As a result, non-owners don't have permissions to attest controls by default. +To be able to attest to controls for your subscription, you should ask the subscription owner to grant you 'Contributor' access to the storage account under the resource group 'AzSKRG'. The storage account looks something like: 'AzSKyyyymmddhhmmss' + +The AzSK docs for control attestation are [here](../00c-Addressing-Control-Failures/Readme.md#control-attestation) + +#### Attestation fails with permission error even though I am Owner. + +It can happen due to below reasons +1. User who is attesting doesn't have Contributor/ Owner access on the AzSKRG
+ Sol. => In this scenario the user is already co-admin. + +2. "AzSK-controls-state" Container is missing in the AzSK storage account
+ Sol. => Run the below script on your subscription after replacing the storage account name. You can find the AzSK storage account under AzSKRG resource group in your subscription + ```PowerShell + $StorageAccountName = "" + $keys = Get-AzStorageAccountKey -ResourceGroupName "AzSKRG" -Name $StorageAccountName + $currentContext = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $keys[0].Value -Protocol Https + $Container = Get-AzStorageContainer -Name "AzSK-controls-state" -Context $currentContext -ErrorAction SilentlyContinue + if($null -eq $Container) + { + New-AzStorageContainer -Name "AzSK-controls-state" -Permission Off -Context $currentContext + } + ``` + +3. AzSKRG resource group is not present on the subscription
+ Sol. => By setting up Continuous Assurance on your subscription will create the required AzSK artifacts. + ```PowerShell + Install-AzSKContinuousAssurance -SubscriptionId "" -ResourceGroupNames "*" -LAWSId "" -LAWSSharedKey "" + ``` + + +#### Why do I have new control failures from AzSK? + +You might come across a scenario that you spent some time and fixed all the issues that you were expected to and "got to green". Now, a few days (or weeks) later, you are seeing that you have to address a bunch of issues. You may wonder - 'What happened? Why do I get new failures from AzSK?' + +There are many reasons why you may see 'new' control failures after you put in the effort to resolve existing ones. Here are some common ones:
+a- You may have net new resources that were created/deployed to the subscription. The first time CA scans these resources (usually within 24 hours of their creation), it will flag any security control failures.
+b- Someone on the team perhaps changed the configuration of an existing resource. In a large subscription with many stakeholders acting on different resources and resource groups, this is quite a possibility. That is where CA helps! It watches over the drift and reports it.
+c- Baseline control set may change. As attacks get sophisticated, so must our defense. It is quite possible that a control that was not considered "core hygiene" might become so a few months down. This will mean that for existing resources, everyone now has a new control to fix.
+d- New controls may get added. Azure is a very dynamic environment. The PG adds new features and security capabilities every quarter in some services and every six months in most others. When a new security feature is added, the AzSK may be modified to add a new control to cover it. If the control is core/fundamental, then everyone will be expected to fix it on existing resources. (Remember that CA automatically picks up latest AzSK bits for scanning. So, the moment a version of AzSK gets released with a new control and it is a 'baseline' control, CA scans will start checking the control on existing resources.)
+e- Control logic for existing controls may change - due to bug fixes or additional conditions in the detection logic. This change in control behavior will, again, start reflecting in CA scans when a version of AzSK with the 'fix' or 'logic change' is released.
+f- Configuration baselines may change. What is considered a mandatory account today may not remain so tomorrow or in 6 months. Certificates expire, credentials/accounts get deprecated. The AzSK is able to detect that your subscription contains these accounts but the access permissions that CA has does not let CA make any changes.
+Phew...We hope we covered the main reasons. One last thought is that in the current "agile + dev ops + cloud" era, with all rapid iterations and changes happening at all layers, security has also become a much more 'continuous' effort compared to the past. + + +#### I am trying to enable diagnostic logs using the recommendation command 'Set-AzDiagnosticSetting' given in the AzSK control. But the command fails with error 'The diagnostic setting 'service' doesn't exist'. How do I resolve this error? + +There is an [open issue](https://github.com/Azure/azure-powershell/issues/6833) with Set-AzDiagnosticSetting command provided by Az. You can enable the diagnostic logs using Azure portal until that issue is resolved. Steps are available [here](https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-archive-diagnostic-logs#archive-diagnostic-logs-using-the-portal). +Just make sure that logs are retained for a minimum of 365 days. + + +#### I wish to deploy virtual networking in a hub and spoke architecture, where ExpressRoute is connected to a Core network, which is then connected via VNET Peering, or VPN to other VNET’s, or other Azure datacentres. But some of the controls regarding ExpressRoute-connected Virtual Networks contradict my requirement. How does AzSK justify the controls like "There should not be another virtual network gateway (GatewayType = Vpn) in an ER-vNet" and "There should not be any virtual network peerings on an ER-vNet"? How should I satisfy them without changing my implementation plans? + +The control regarding ‘do not peer another vNet with ER-connected vNet’ is a precautionary one and one that we expect would apply to most typical users of ER-Networks. However, when there are advanced users/scenarios like the one described above, you can certainly ‘attest’ the control and tell the DevOps Kit to treat it as passed in the future. However, it assumes that the person/team doing so is doing the proper diligence in ensuring that the configuration is setup securely and that it would not lead to new pathways between the wild internet and the corporate environment. + +This same thinking applies to many of the other network-infra related controls. For example, we have a control that flags off ‘IP forwarding’. This would apply to 99% of scenarios…however, there are legit cases where the control may not apply and can be ‘attested’ (e.g., you may be doing additional traffic inspection using a virtual appliance on a network). + +To understand the concept of attestation and how it works, you can go through the other FAQs in the Addressing Control Failures section in our documentation. + +#### I am unable to evaluate/attest some Key Vault controls even with co-admin privilege. I am getting the error: Skipping attestation process for this control. You do not have required permissions to evaluate this control.(Please note that you must have access permissions to the keys & secrets in the key vault for successful attestation of this control) (If you are 'Owner' then please elevate to 'Co-Admin' in the portal and re-run in a *fresh* PS console.) + +Some key vault controls require permission(‘Get and ’List’) on keys and secrets to check certain properties like expiry date etc. If the user account/application does not have access on the keys and secrets stored in the key vault resource, then the scan will result into ‘Manual’ state as the control will not get evaluated due to insufficient permission. In such cases where the user/application is not able to evaluate any control due to permission issues then it must not be attesting them without knowing the actual risk. + +Ensure the user account/application executing the scan commands has atleast ‘Get’ and ‘List’ (read permissions) Key and Secret Permissions. [Azure Portal -> Key Vault resource -> Access Policy -> User/Application -> Enable ‘get’ and ‘List’ in Key Permissions + Secret Permissions] + +#### I am unable to scan/attest API connection controls independently. I am getting the error: Could not find any resources to scan under Resource Group. InvalidOperation: Could not find any resources that match the specified criteria. How should I scan and bulk attest API connection controls? + +In the DevOps kit, API connections are scanned as child resource of Logic App. To scan/attest controls associated with API connection, you need to scan the parent logic app and the child resources will get scanned with it. Please note that bulk attestation is not supported in this case. API connection controls can only be attested sequentially using the below command: + +``` +# Scan a specific Logic App and the API connections associated with the app +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ResourceTypeName LogicApps -ResourceNames -ControlsToAttest NotAttested + +# Scan all Logic Apps and the API connections associated with those apps +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ResourceTypeName LogicApps -ControlsToAttest NotAttested +``` -[Back to top...](Readme.md#contents) \ No newline at end of file +#### I cannot find the API connection on portal that is listed in the AzSK CSV scan result. Where can I find these resource on portal? + +You may come across a scenario where you get multiple API connections in the scan result, but they are not available on portal. These API connections are Connectors that being used by your Logic App. To view these connectors, go to your Logic App --> Logic App Designer. Here is a document on various types of [Connectors for Azure Logic Apps](https://docs.microsoft.com/en-us/azure/connectors/apis-list). + + +#### How do I remediate failing control Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG? + +The time taken to evaluate control Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG, is directly proportional to the number of resource groups you have in your subscription AND total number of identities that have access on those resource groups. As a result, the GSS scan may take significant amount of time to complete for subscriptions with multiple resource groups. Hence, we have enabled this control only in CA mode. In manual mode, we skip the actual control scan and instruct the user to see the evaluation details about this control in the CA job scans. +If you have addressed the causes for control failure and you need to manually scan the control, you can override the current behavior by explicitly specifying the controlId in the scan cmdlet as shown below. + +``` +Import-Module AzSK + +Get-AzSKSubscriptionSecurityStatus -SubscriptionId $subid -ControlId Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG +``` + +#### How do I remediate failing control Azure_APIManagement_DP_Use_Secure_TLS_Version? + +3DES Ciphers, TLS protocols (1.1 and 1.0) and SSL 3.0 are outdated versions. Using these can expose the API to meet-in-the-middle attack, chosen-plaintext or known-plaintext attacks. Use the following command to disable the aforementioned configurations. + +Make sure you test the implications before changing the configuration. + +Please note that this command may take 15 to 20 minutes to update the configuration. + +``` +# Enter SubscriptionId, ResourceGroupName, APIMServiceName +$SubscriptionId = '' +$ResourceGroupName = '' +$APIMServiceName = '' + +Set-AzContext $SubscriptionId + +# Get API Management service instance +$apim = Get-AzResource -Name $APIMServiceName -ResourceGroupName $ResourceGroupName -ResourceType Microsoft.ApiManagement/service + +# Turn off unsecure protocol and cipher configurations +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TripleDes168' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10' = "false" +$apim.Properties.customProperties.'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11' = "false" + +# Save the updated configuration +$apim | Set-AzResource -Force + +``` + +#### How do I remediate failing control Azure_AppService_DP_Use_Secure_TLS_Version? + +Using latest TLS version significantly reduces risks from security design issues and security bugs that may be present in older versions. If you are noticing this control failing for your app service, use the following command to set minimum TLS version to 1.2. + +Make sure you test the implications before changing the configuration. + +``` +# Enter SubscriptionId, ResourceGroupName, AppServiceName +$SubscriptionId = '' +$ResourceGroupName = '' +$AppServiceName = '' + +Set-AzContext $SubscriptionId + +# Update TLS version +Get-AzResource -ResourceType Microsoft.Web/sites -ResourceGroupName $ResourceGroupName -Name $AppServiceName | ForEach-Object { + + $params = @{ + ApiVersion = '2018-02-01' + ResourceName = '{0}/web' -f $_.Name + ResourceGroupName = $_.ResourceGroupName + PropertyObject = @{ minTlsVersion = 1.2 } + ResourceType = 'Microsoft.Web/sites/config' + } + +Set-AzResource @params -Force +} +``` + +#### Many of the Azure Databricks control goes to manual state from both CA and local scan. What should I do to evaluate Azure Databricks resources properly? + +Some of the controls of Azure Databricks (ADB) can not be scanned properly from CA as they need ADB workspace's personal access token (PAT) with admin privileges. In local scan also by default such controls will go to manual state as it requires PAT to evaluate these controls and DevOps Kit will not prompt for PAT (instead it will try to read PAT via session variable) as it will result in halting the scan progress untill PAT is provided. +So, to evaluate ADB controls properly from local scan mode, please set a session variable named 'ADBPatsForAzSK' with required value as shown in example below: + +``` +# For a single ADB workspace +Set-Variable 'ADBPatsForAzSK' -Scope Global -Value @{'ADBResourceName' = 'Personal access token'} + +# For multiple ADB workspaces +Set-Variable 'ADBPatsForAzSK' -Scope Global -Value @{'ADBResourceName1' = 'Personal access token 1'; + 'ADBResourceName2' = 'Personal access token 2'} + +``` +Then in the same session please run scan command as follows: + +``` +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ResourceTypeName Databricks -ResourceNames + +``` + +[Back to top...](Readme.md#contents) diff --git a/01-Subscription-Security/ASCPoliciesCoverage.md b/01-Subscription-Security/ASCPoliciesCoverage.md new file mode 100644 index 00000000..a0e33c12 --- /dev/null +++ b/01-Subscription-Security/ASCPoliciesCoverage.md @@ -0,0 +1,170 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + +

List of 'ASC default initiative' policies enabled via AzSK

+ +

Mandatory ASC policies

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PolicyDescription
Audit remote debugging state for an API AppRemote debugging requires inbound ports to be opened on an API app. Remote debugging should be turned off.
Audit remote debugging state for a Function AppRemote debugging requires inbound ports to be opened on a function app. Remote debugging should be turned off.
Audit remote debugging state for a Web ApplicationRemote debugging requires inbound ports to be opened on a web application. Remote debugging should be turned off.
Audit HTTPS only access for an API AppUse of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks.
Audit HTTPS only access for a Function AppUse of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks.
Audit HTTPS only access for a Web ApplicationUse of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks.
Audit enabling of only secure connections to your Redis CacheAudit enabling of only connections via SSL to Redis Cache. Use of secure connections ensures authentication between the server and the service and protects data in transit from network layer attacks such as man-in-the-middle, eavesdropping, and session-hijacking
Audit usage of Azure Active Directory for client authentication in Service FabricAudit usage of client authentication only via Azure Active Directory in Service Fabric
Audit the setting of ClusterProtectionLevel property to EncryptAndSign in Service FabricService Fabric provides three levels of protection (None, Sign and EncryptAndSign) for node-to-node communication using a primary cluster certificate. Set the protection level to ensure that all node-to-node messages are encrypted and digitally signed
Audit SQL servers without Advanced Data SecurityAudit SQL servers without Advanced Data Security
Audit provisioning of an Azure Active Directory administrator for SQL serverAudit provisioning of an Azure Active Directory administrator for your SQL server to enable Azure AD authentication. Azure AD authentication enables simplified permission management and centralized identity management of database users and other Microsoft services
Monitor unencrypted SQL databases in Azure Security CenterUnencrypted SQL databases will be monitored by Azure Security Center as recommendations
Audit unrestricted network access to storage accountsAudit unrestricted network access in your storage account firewall settings. Instead, configure network rules so only applications from allowed networks can access the storage account. To allow connections from specific internet or on-premise clients, access can be granted to traffic from specific Azure virtual networks or to public internet IP address ranges
Audit secure transfer to storage accountsAudit requirment of Secure transfer in your storage account. Secure transfer is an option that forces your storage account to accept requests only from secure connections (HTTPS). Use of HTTPS ensures authentication between the server and the service and protects data in transit from network layer attacks such as man-in-the-middle, eavesdropping, and session-hijacking
Audit external accounts with owner permissions on a subscriptionExternal accounts with owner permissions should be removed from your subscription in order to prevent unmonitored access.
Audit external accounts with write permissions on a subscriptionExternal accounts with write privileges should be removed from your subscription in order to prevent unmonitored access.
Audit external accounts with read permissions on a subscriptionExternal accounts with read privileges should be removed from your subscription in order to prevent unmonitored access.
Audit deprecated accounts on a subscriptionDeprecated accounts should be removed from your subscriptions. Deprecated accounts are accounts that have been blocked from signing in.
Audit use of classic storage accountsUse new Azure Resource Manager v2 for your storage accounts to provide security enhancements such as: stronger access control (RBAC), better auditing, Azure Resource Manager based deployment and governance, access to managed identities, access to key vault for secrets, Azure AD-based authentication and support for tags and resource groups for easier security management
Audit use of classic virtual machinesUse new Azure Resource Manager v2 for your virtual machines to provide security enhancements such as: stronger access control (RBAC), better auditing, ARM-based deployment and governance, access to managed identities, access to key vault for secrets, Azure AD-based authentication and support for tags and resource groups for easier security management
Monitor unencrypted VM Disks in Azure Security CenterVMs without an enabled disk encryption will be monitored by Azure Security Center as recommendations
Monitor OS vulnerabilities in Azure Security CenterServers which do not satisfy the configured baseline will be monitored by Azure Security Center as recommendations
Monitor VM Vulnerabilities in Azure Security CenterMonitors vulnerabilities detected by Vulnerability Assessment solution and VMs without a Vulnerability Assessment solution in Azure Security Center as recommendations.
Monitor missing Endpoint Protection in Azure Security CenterServers without an installed Endpoint Protection agent will be monitored by Azure Security Center as recommendations
Monitor missing system updates in Azure Security CenterMissing security system updates on your servers will be monitored by Azure Security Center as recommendations
Audit OS vulnerabilities on your virtual machine scale sets in Azure Security CenterAudit the OS vulnerabilities on your virtual machine scale sets to protect them from attacks.
Audit the endpoint protection solution on virtual machine scale sets in Azure Security CenterAudit the existence and health of an endpoint protection solution on your virtual machines scale sets, to protect them from threats and vulnerabilities.
Audit any missing system updates on virtual machine scale sets in Azure Security CenterAudit whether there are any missing system security updates and critical updates that should be installed to ensure that your Windows and Linux virtual machine scale sets are secure.
Monitor SQL vulnerability assessment results in Azure Security CenterMonitor Vulnerability Assessment scan results and recommendations for how to remediate database vulnerabilities.
Audit accounts with owner permissions who are not MFA enabled on a subscriptionMulti-Factor Authentication (MFA) should be enabled for all subscription accounts with owner permissions to prevent a breach of accounts or resources.
Audit accounts with write permissions who are not MFA enabled on a subscriptionMulti-Factor Authentication (MFA) should be enabled for all subscription accounts with write privileges to prevent a breach of accounts or resources.
Audit accounts with read permissions who are not MFA enabled on a subscriptionMulti-Factor Authentication (MFA) should be enabled for all subscription accounts with read privileges to prevent a breach of accounts or resources.
Audit standard tier of DDoS protection is enabled for a virtual networkDDoS protection standard should be enabled for all virtual networks with a subnet that is part of an application gateway with a public IP.
Audit SQL managed instances without Advanced Data SecurityAudit SQL managed instances without Advanced Data Security
+ +

Optional ASC policies

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PolicyDescription
Audit CORS resource access restrictions for an API AppCross origin Resource Sharing (CORS) should not allow all domains to access your API app. Allow only required domains to interact with your API app.
Audit CORS resource access restrictions for a Function AppCross origin Resource Sharing (CORS) should not allow all domains to access your Function app. Allow only required domains to interact with your Function app.
Audit CORS resource access restrictions for a Web ApplicationCross origin Resource Sharing (CORS) should not allow all domains to access your web application. Allow only required domains to interact with your web app.
Audit enabling of diagnostic logs in App ServicesAudit enabling of diagnostic logs on the app. This enables you to recreate activity trails for investigation purposes if a security incident occurs or your network is compromised
Audit enablement of encryption of Automation account variablesIt is important to enable encryption of Automation account variable assets when storing sensitive data
Audit enabling of diagnostic logs in Batch accountsAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit configuration of metric alert rules on Batch accountsAudit configuration of metric alert rules on Batch account to enable the required metric
Audit enabling of diagnostic logs in Data Lake AnalyticsAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit enabling of diagnostic logs in Azure Data Lake StoreAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit enabling of diagnostic logs in Event HubAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit authorization rules on Event Hub namespacesEvent Hub clients should not use a namespace level access policy that provides access to all queues and topics in a namespace. To align with the least privilege security model, you shoud create access policies at the entity level for queues and topics to provide access to only the specific entity
Audit existence of authorization rules on Event Hub entitiesAudit existence of authorization rules on Event Hub entities to grant least-privileged access
Audit enabling of diagnostic logs in Key VaultAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit enabling of diagnostic logs in Logic AppsAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit enabling of diagnostic logs for Search serviceAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit enabling of diagnostic logs in Service BusAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit authorization rules on Service Bus namespacesService Bus clients should not use a namespace level access policy that provides access to all queues and topics in a namespace. To align with the least privilege security model, you shoud create access policies at the entity level for queues and topics to provide access to only the specific entity
Audit enabling of diagnostics logs in Service Fabric and Virtual Machine Scale SetsIt is recommended to enable Logs so that activity trail can be recreated when investigations are required in the event of an incident or a compromise.
Audit SQL server level Auditing settingsAudits the existence of SQL Auditing at the server level
Monitor unaudited SQL servers in Azure Security CenterSQL servers which don't have SQL auditing turned on will be monitored by Azure Security Center as recommendations
Audit enabling of diagnostic logs in Azure Stream AnalyticsAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Audit usage of custom RBAC rulesAudit built-in roles such as 'Owner, Contributer, Reader' instead of custom RBAC roles, which are error prone. Using custom roles is treated as an exception and requires a rigorous review and threat modeling
Audit maximum number of owners for a subscriptionIt is recommended to designate up to 3 subscription owners in order to reduce the potential for breach by a compromised owner.
Audit minimum number of owners for subscriptionIt is recommended to designate more than one subscription owner in order to have administrator access redundancy.
Audit deprecated accounts with owner permissions on a subscriptionDeprecated accounts with owner permissions should be removed from your subscription. Deprecated accounts are accounts that have been blocked from signing in.
[Preview]: Monitor open management ports on Virtual MachinesOpen remote management ports are exposing your VM to a high level of risk from Internet-based attacks. These attacks attempt to brute force credentials to gain admin access to the machine.
Monitor Internet-facing virtual machines for Network Security Group traffic hardening recommendationsAzure Security Center analyzes the traffic patterns of Internet facing virtual machines and provides Network Security Group rule recommendations that reduce the potential attack surface
Monitor permissive network access in Azure Security CenterNetwork Security Groups with too permissive rules will be monitored by Azure Security Center as recommendations
[Preview]: Monitor IP forwarding on virtual machinesEnabling IP forwarding on a virtual machine's NIC allows the machine to receive traffic addressed to other destinations. IP forwarding is rarely required (e.g., when using the VM as a network virtual appliance), and therefore, this should be reviewed by the network security team.
Audit enabling of diagnostic logs in IoT HubsAudit enabling of diagnostic logs. This enables you to recreate activity trails to use for investigation purposes; when a security incident occurs or when your network is compromised
Monitor possible network Just In Time (JIT) access in Azure Security CenterPossible network Just In Time (JIT) access will be monitored by Azure Security Center as recommendations
Monitor possible app Whitelisting in Azure Security CenterPossible Application Whitelist configuration will be monitored by Azure Security Center
Monitor permissive network access of VMs running web-apps in Azure Security CenterAzure security center has discovered that some of your virtual machines are running web applications, and the NSGs associated to these virtual machines are overly permissive with regards to the web application ports
Monitor unprotected network endpoints in Azure Security CenterNetwork endpoints without a Next Generation Firewall's protection will be monitored by Azure Security Center as recommendations
[Preview]: Monitor SQL data discovery and classification recommendations in Azure Security CenterAzure Security Center monitors the data discovery and classification scan results for your SQL databases and provides recommendations to classify the sensitive data in your databases for better monitoring and security
Audit SQL servers without Vulnerability AssessmentAudit Azure SQL servers which do not have recurring vulnerability assessment scans enabled. Vulnerability assessment can discover, track, and help you remediate potential database vulnerabilities.
Audit SQL managed instances without Vulnerability AssessmentAudit SQL managed instances which do not have recurring vulnerability assessment scans enabled. Vulnerability assessment can discover, track, and help you remediate potential database vulnerabilities.
[Preview]: Monitor permissive network access to app-servicesAzure security center has discovered that the networking configuration of some of your app services are overly permissive and allow inbound traffic from ranges that are too broad
+ + + diff --git a/01-Subscription-Security/PIMSampleScript.ps1 b/01-Subscription-Security/PIMSampleScript.ps1 new file mode 100644 index 00000000..73682b17 --- /dev/null +++ b/01-Subscription-Security/PIMSampleScript.ps1 @@ -0,0 +1,80 @@ + + + $subid = '' + import-module AzSK + + + +#===================================================================== + +# AzSK PIM helper Commands : Refer https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1 + +# There are two use cases for AzSK PIM commands: Admin and Owner + +#-------------------------------------------------------- + +# For Admins + +#-------------------------------------------------------- + +# To onboard a subscription to PIM, refer https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-resource-roles-discover-resources#discover-resources + +# Assuming the subscription/resource is onboarded you can assign PIM roles to users + + $days = + $userId = + setpim -AssignRole -SubscriptionId $subid -RoleName 'Owner' -PrincipalName $userId -DurationInDays $days + + +# If it is likely that you have a lot of permanent assignments and you need to migrate those users to PIM-based model. +# This can be achieve in 2 steps... first 'mirror' the permanent memberships as PIM assignments and then remove permanent ones + +# Step-1: To mirror existing permanent assignments for a particular role in the subscription, use the below command: + + setpim -AssignEligibleforPermanentAssignments -SubscriptionId $subid -RoleNames 'Owner' -DurationInDays $days + +# Step-2: To remove those permanent assignments (that should now have matching PIM assignments) run the below command + + setpim -RemovePermanentAssignments -SubscriptionId $subid -RoleNames 'Owner' -RemoveAssignmentFor MatchingEligibleAssignments + +# You can validate expected changes by checking the current state of PIM and permanent assignments as below: + + getpim -ListPermanentAssignments -SubscriptionId $subid -RoleNames 'Owner' + + getpim -ListPIMAssignments -SubscriptionId $subid -RoleNames 'Owner' + +# Note that the commands above can in general be used to check permanend and PIM-assigned members for various scopes and roles. + + +# Once you have assigned members, periodically, their assignments will near expiry (or may expire) and will need renewal. + +# This can be done by using appropriate values below (extend by 'x' days assignments that are going to expire in the next 'y' days) for the given role and scope + + setpim -ExtendExpiringAssignments -RoleNames 'Contributor' -SubscriptionId $subid -ExpiringInDays y -DurationInDays x # Use '-Force' switch to extend all assignments without interactive workflow + + + +# See the DevOps Kit PIM docs (links above) for more. + + +#------------------------------------------------------- + +# For End Users: + +#------------------------------------------------------- + +# As a user you can check your current PIM assignments by using: + + getpim -ListMyEligibleRoles + + + +# Activating and deactivating assigned roles is a snap. To activate, you can use a command such as: + + setpim -ActivateMyRole -SubscriptionId $subid -RoleName 'Owner' -DurationInHours $days -Justification $justification + + + +# The above assignment can be deactivated using: + + setpim -DeactivateMyRole -SubscriptionId $subid -RoleName 'Owner' diff --git a/01-Subscription-Security/Readme.md b/01-Subscription-Security/Readme.md index c0818254..4de12853 100644 --- a/01-Subscription-Security/Readme.md +++ b/01-Subscription-Security/Readme.md @@ -1,6 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # AzSK Subscription Security Package -![Subscription_Security](../Images/Subscription_Security.JPG) +![Subscription_Security](../Images/Subscription_Security.png) ### Contents: @@ -18,7 +23,7 @@ - [Remove previously provisioned security settings from your subscription](Readme.md#remove-azsk-subscription-security-provisioning-from-your-subscription) - [FAQs](Readme.md#faqs-1) -### [AzSK: Subscription AccessControl Provisioning](Readme.md#azsk-subscription-access-control-provisioning) +### [AzSK: Subscription Access Control Provisioning](Readme.md#azsk-subscription-access-control-provisioning) - [Overview](Readme.md#overview-2) - [Setup pre-approved mandatory accounts](Readme.md#setup-pre-approved-mandatory-accounts) - [Remove pre-approved mandatory accounts](Readme.md#remove-previously-provisioned-accounts) @@ -45,6 +50,18 @@ ### [AzSK: Update subscription security baseline configuration](Readme.md#azsk-update-subscription-security-baseline-configuration-1) - [Update subscription security baseline configuration](Readme.md#update-subscription-security-baseline-configuration) +### [AzSK support for Azure Government and Azure China](Readme.md#azsk-support-for-azure-government-and-azure-china-1) + +- [Spotcheck/Manual Scans](Readme.md#spotcheckmanual-scans) +- [CICD](Readme.md#cicd) +- [CA](Readme.md#ca) +- [Customizing AzSK for your organization](Readme.md#customizing-azsk-for-your-organization) + +### [AzSK: Privileged Identity Management (PIM) helper cmdlets](Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) +- [Get-AzSKPIMConfiguration at Subscription scope](Readme.md#use-get-azskpimconfiguration-alias-getpim-for-querying-various-pim-settingsstatus-at-subscription-scope) +- [Set-AzSKPIMConfiguration at Subscription scope](Readme.md#use-set-azskpimconfiguration-alias-setpim-for-configuringchanging-pim-settings-at-subscription-scope) +- [Get-AzSKPIMConfiguration at Management Group scope](Readme.md#use-get-azskpimconfiguration-alias-getpim-for-querying-various-pim-settingsstatus-at-management-group-level) +- [Set-AzSKPIMConfiguration at Management Group scope](Readme.md#use-set-azskpimconfiguration-alias-setpim-for-configuringchanging-pim-settings-at-management-group-level) ---------------------------------------------------------- ## AzSK: Subscription Health Scan @@ -101,7 +118,7 @@ The next section explains how to interpret output in the LOG file and how to add All cmdlets in AzSK generate outputs which are organized as under: - summary information of the control evaluation (pass/fail) status in a CSV file, - detailed control evaluation log in a LOG file and -- a few other anciliary files for additional support +- a few other ancillary files for additional support The overall layout and files in the output folder are also described in the README.txt file present in the root output folder. @@ -129,15 +146,15 @@ provisioning mandatory accounts). The subscription health check supports multiple parameters as specified below: - SubscriptionId – Subscription ID is the identifier of your Azure subscription -- FilterTags - Comma-seperated tags to filter the security controls. E.g., RBAC, SOX, AuthN, etc. -- ExcludeTags - Comma-seperated tags to exclude the security controls. E.g., RBAC, SOX, AuthN, etc. -- ControlIds - Comma-seperated AzSK control id's to filter security controls. E.g., Azure_Subscription_AuthZ_Limit_Admin_Owner_Count, Azure_Subscription_Config_Azure_Security_Center, etc. +- FilterTags - Comma-separated tags to filter the security controls. E.g., RBAC, SOX, AuthN, etc. +- ExcludeTags - Comma-separated tags to exclude the security controls. E.g., RBAC, SOX, AuthN, etc. +- ControlIds - Comma-separated AzSK control id's to filter security controls. E.g., Azure_Subscription_AuthZ_Limit_Admin_Owner_Count, Azure_Subscription_Config_Azure_Security_Center, etc. ```PowerShell Get-AzSKSubscriptionSecurityStatus -SubscriptionId [-ControlIds ] [-FilterTags ] [-ExcludeTags ] ``` These different parameters would enable you to execute different 'flavors' of subscription health scan. For example, they will let you scan only SOX relevant controls or AuthZ related controls or -exclude best practices or even execute one specifc control. +exclude best practices or even execute one specific control. Here are some examples: 1. Execute only SOX related controls @@ -154,8 +171,39 @@ Get-AzSKSubscriptionSecurityStatus -SubscriptionId -FilterTags Get-AzSKSubscriptionSecurityStatus -SubscriptionId -ControlIds Azure_Subscription_Config_Azure_Security_Center ``` -[Back to top…](Readme.md#contents) -### FAQs +|List of Tags|Purpose| +|-------|-------| +|Access|Access activities| +|ACLS|Access control activities| +|AppService|Azure App Services| +|Audit|Audit activities| +|AuthN|Authentication activities| +|AuthZ|Authorization activities| +|Automated|Controls which are automated by AzSK| +|Availability|Availability| +|BCDR|Backup and disaster recovery| +|Best Practice|Controls which should be implemented to ensure your application security| +|Classic|Classic services| +|Config|Configurations| +|Deploy|Deployment activities| +|Diagnostics|Diagnostics activities| +|DP|Data protection| +|FunctionApp|Azure FunctionApp| +|Information|Controls which are default behaviour by Azure but additional check for notification| +|KeyRotation|Key rotation| +|KeySecretPermissions|Controls which can be attested only when the user has access permissions on the concerned keys and secrets| +|Linux|Linux virtual machine| +|Manual|Controls which are not automated and user need to verify it manually| +|NetSec|Network security| +|OwnerAccess|Controls which require owner/co-admin permission to get required output| +|RBAC|Role based access controls| +|SDL|Software development lifecycle | +|SecIntell|Security intellisense | +|SI|System integrity | +|SOX|Controls which are enforced by SOX| +|SqlDatabase|Azure SQL Database| +|TCP|Controls which must be implemented to ensure your application security| +|Windows|Windows virtual machine| [Back to top…](Readme.md#contents) @@ -181,7 +229,7 @@ Set-AzSKSubscriptionSecurity -SubscriptionId -SecurityContactEm ``` |Config Param Name |Purpose | | --------------- | -------- | -|SecurityContactEmails |Comma-separated list of emails (e.g., 'abc@microsoft.com, def.microsoft.com') for contact preference| +|SecurityContactEmails |Comma-separated list of emails (e.g., 'abc@microsoft.com, def@microsoft.com') for contact preference| |SecurityPhoneNumber |Single phone number (e.g., '425-882-8080' or '+91-98765-43210' or '+1-425-882-8080') for contact preference| > **Note**: @@ -201,7 +249,7 @@ Remove-AzSKSubscriptionSecurity -SubscriptionId -Tags 'Security policy'. +3. Select your subscription and click on 'Edit settings'. +4. Select 'Email notifications'. +5. Update 'Security contact emails' and 'Phone number'. +6. Click on 'Save'. + +You can try running the recommendation command again after doing the above change. + [Back to top…](Readme.md#contents) ------------------------------------------------------------ @@ -270,7 +331,7 @@ Remove-AzSKSubscriptionRBAC -SubscriptionId [-Tags ] #### Subscription Activity Alerts (based on Azure Insights) > **Note**: The alerts setup covered on this page uses the native 'Insights-based' alerts mechanism -offered by the Azure PG. In the 'Alerting & Monitoring' section, we also cover support for OMS-based +offered by the Azure PG. In the 'Alerting & Monitoring' section, we also cover support for Log Analytics-based alerts which enable similar scenarios (and more). We have found that both approaches are in use across LoB application teams. @@ -309,24 +370,14 @@ Remove-AzSKAlerts -SubscriptionId -Tags |Config Param Name |Purpose | | ---------------- | --------- | |SubscriptionID |Subscription ID against which these alerts would be setup| -|Tags |Comma-separated alert tag names which needs to be removed| - -**Note**: This command cleans up all alerts in the resource group 'AzSKRG'. This resource group is used internally as a container for AzSK objects. As a result, it is advisable to not add other alerts (or other types of resources) to this RG. - -[Back to top…](Readme.md#contents) -### Configure alerts scoped to specific resource groups -You may be interested in enabling alerts but only for resources within a particular (target) resource group. This may be done using the -TargetResourceGroup parameter. +|Tags |Comma-separated alert tag names which needs to be removed, supported tag names "Optional","Mandatory","SMS"| -Run the below command +For e.g., to remove only optional alerts, run following command: ```PowerShell -Set-AzSKAlerts -SubscriptionId -TargetResourceGroup +Remove-AzSKAlerts -SubscriptionId -Tags "Optional" ``` -These parameters above has to be updated with the appropriate values. See the table below for details. -|Config Param Name |Purpose | -| ----------------- | --------- | -|SubscriptionId |Subscription ID against which these alerts would be setup | -|TargetResourceGroup |Target resource group on which alerts needs to be configured | +**Note**: This command cleans up all alerts in the resource group 'AzSKRG' with matched tag. This resource group is used internally as a container for AzSK objects. As a result, it is advisable to not add other alerts (or other types of resources) to this RG. [Back to top…](Readme.md#contents) ### FAQs @@ -342,13 +393,13 @@ These alerts template and the generation is completely controlled through Azure #### Is there a record maintained of the alerts that have fired? You could run the below command to check the alerts raised on the subscription. ```PowerShell -Get-AzureRmLog | where {$_.OperationName -eq "Microsoft.Insights/AlertRules/Activated/Action"} +Get-AzLog | where {$_.OperationName -eq "Microsoft.Insights/AlertRules/Activated/Action"} ``` #### Troubleshooting |Error Description |Comments| | -------------- | ------- | |Error: Please enter valid subscription id!| Provided subscription id is incorrect| -|Error Occurred! Try running the command with -Debug option for more details. |Failed to setup the policy. Share the details of the errors to AzSKSupExt@microsoft.com| +|Error Occurred! Try running the command with -Debug option for more details. |Failed to setup the policy. Share the details of the errors to AzSKSup@microsoft.com| [Back to top…](Readme.md#contents) @@ -358,8 +409,9 @@ Get-AzureRmLog | where {$_.OperationName -eq "Microsoft.Insights/AlertRules/Acti ### Setup Azure Security Center (ASC) on your subscription The Set-AzSKAzureSecurityCenterPolicies provisions the following for Azure Security Center (ASC) configuration: -1. Configure Azure Security Center by enabling all policies and rules. +1. Configure Azure Security Center by enabling all the required policies and rules. 2. Configure email address and phone number for contact preferences. +3. Enable automatic provisioning for the subscription. **Prerequisites:** 1. You need to be owner on the subscription which you want to onboard on to ASC. @@ -367,20 +419,22 @@ The Set-AzSKAzureSecurityCenterPolicies provisions the following for Azure Secur **Steps to onboard onto ASC:** 1. Open PowerShell under non admin mode. -2. Login into your Azure Account using Login-AzureRmAccount. +2. Login into your Azure Account using Connect-AzAccount. 3. Run the below command with the subscriptionId on which you want to configure Azure Security Center. ```PowerShell Set-AzSKAzureSecurityCenterPolicies -SubscriptionId ` -SecurityContactEmails ` - -SecurityPhoneNumber + -SecurityPhoneNumber ` + [-OptionalPolicies] ``` |Config Param Name |Purpose | | --------------- | -------- | |SubscriptionId |Subscription ID against which ASC would be setup | -|SecurityContactEmails |Comma-separated list of emails (e.g., 'abc@microsoft.com, def.microsoft.com') for contact preference| +|SecurityContactEmails |Comma-separated list of emails (e.g., 'abc@microsoft.com, def@microsoft.com') for contact preference| |SecurityPhoneNumber |Single phone number (e.g., '425-882-8080' or '+91-98765-43210' or '+1-425-882-8080') for contact preference| +|OptionalPolicies |Switch to enable policies which are marked as optional| -This command will *overwrite* the contact emails and contact phone previously set in Azure Security Center. +This command will *overwrite* the contact emails and contact phone previously set in Azure Security Center. Here is the [list](../01-Subscription-Security/ASCPoliciesCoverage.md) of all the policies (both mandatory & optional) that are enabled via this command. >**Note:** The Get-AzSKSubscriptionSecurityStatus cmdlet can be used to check Azure Security Center settings (amongst other things). That script checks for the following w.r.t. Azure Security Center: >1. All ASC policies are configured per expectation. @@ -402,7 +456,7 @@ You can install the ARM policies via the Set-AzSKARMPolicies cmdlet as below: 1. Login to your Azure Subscription using below command ```PowerShell -Login-AzureRmAccount +Connect-AzAccount ``` 2. Once you have installed the AzSK, you should be able to run the below command @@ -438,7 +492,7 @@ The ARM policy configuration script currently enables the policies (Refer the li #### How can I check for policy violations? You could run the below command to check for the policy violations on the subscription. By default this shows the violations for the last one hour. Other intervals can be specified. ```PowerShell -Get-AzureRmLog | where {$_.OperationName -eq "Microsoft.Authorization/policies/audit/action"} +Get-AzLog | where {$_.OperationName -eq "Microsoft.Authorization/policies/audit/action"} ``` Refer to this [MSDN article](https://azure.microsoft.com/en-in/documentation/articles/resource-manager-policy/#policy-audit-events) for more details @@ -456,9 +510,9 @@ We have covered for the below resource types so far: |Error Description |Comments| | ----------------- |--------| |Error: Please enter valid subscription id! |Provided subscription id is incorrect| -|Error Occurred! Try running the command with -Debug option for more details. |Failed to setup the policy. Share the details of the errors to AzSDKSupExt@microsoft.com | +|Error Occurred! Try running the command with -Debug option for more details. |Failed to setup the policy. Share the details of the errors to AzSKSup@microsoft.com | -Reach out to AzSDKSupExt@microsoft.com for any further help +Reach out to AzSKSup@microsoft.com for any further help [Back to top…](Readme.md#contents) @@ -481,3 +535,933 @@ Update-AzSKSubscriptionSecurity -SubscriptionId [Back to top…](Readme.md#contents) + +## AzSK support for Azure Government and Azure China + +>**Pre-requisites**: +> - AzSK version 3.8.0 or above. + +From release 3.8.0, AzSK has started supporting a few core scenarios for Azure Government and Azure China environments. Please follow the steps as under to use AzSK in those environments. + +### Spotcheck/Manual Scans: + +Follow the steps below to successfully run the local AzSK scans (GRS, GSS and other commands): + +1. Follow instructions in our [installation guide](../00a-Setup#installation-guide) to download the latest version of AzSK (3.9.0 or above). + +2. Configure AzSK for your Azure environment using the following command: +```PowerShell +Set-AzSKPolicySettings -AzureEnvironment '' +``` +```PowerShell +E.g., Set-AzSKPolicySettings -AzureEnvironment AzureUSGovernment +``` + +Once you have run through the steps above, any AzSK commands you run will start targeting the configured Azure cloud environment. + +Notes: + * When no specific environment is configured (as in Step-2 above), AzSK assume AzureCloud as the default environment. + * If you have access to multiple Azure environments and need to switch from one to the other (e.g., AzurePublic to AzureChina) then you can use the Clear-AzSKSessionState command after running Step-2. This will cause AzSK to reload the newly configured environment. + +### CICD: + +To use the CICD extension, no special steps are required beyond those outlined in the AzSK CICD extensions [doc](../03-Security-In-CICD#contents). + + +### CA: + +Once you have run through the steps outlined in the 'Spotcheck/Manual' section, You can easily use AzSK Continuous Assurance. Click [here](/04-Continous-Assurance#continuous-assurance-ca) for more details on Continuous Assurance. + +Please refer [this](../04-Continous-Assurance/Readme.md#setting-up-continuous-assurance---step-by-step) set up CA. As Azure Government and Azure China are limited to particular location, provide 'AutomationAccountLocation' parameter because the default value is EastUS2. + +```PowerShell +E.g., Install-AzSKContinuousAssurance -SubscriptionId ` + -AutomationAccountLocation "USGov Virginia" ` (for Azure Government) + -ResourceGroupNames ` + -LAWSId ` + -LAWSSharedKey +``` + +### Customizing AzSK for your organization: + +Please refer [this](../07-Customizing-AzSK-for-your-Org#customizing-azsk-for-your-organization) for more details + +Note: + +As Azure Government and Azure China are limited to particular location, provide 'ResourceGroupLocation' parameter because the default value is EastUS2 + +```PowerShell +E.g., Install-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName ` + -PolicyFolderPath ` + -ResourceGroupLocation "USGov Virginia" ` + -AppInsightLocation "USGov Virginia" (for Azure Government) +``` + +## AzSK: Privileged Identity Management (PIM) helper cmdlets + +AzSK now supports the Privileged Identity Management (PIM) helper cmdlets. This command provides a quicker way to perform Privileged Identity Management (PIM) operations and enables you to manage access to important Azure subscriptions, resource groups and resources. + +### Use Get-AzSKPIMConfiguration (alias 'getpim') for querying various PIM settings/status at Subscription scope + + 1.

List your PIM-eligible roles (-ListMyEligibleRoles)

+ + Use this command to list eligible PIM roles in the selected Azure subscription. + + ```PowerShell + Get-AzSKPIMConfiguration -ListMyEligibleRoles + ``` + + 2.

List permanent assignments (-ListPermanentAssignments)

+ + Use this command to list Azure role with permanent assignments at the specified scope. By default, it lists all role assignments in the selected Azure subscription. Use respective parameters to list assignments for a specific role, or to list assignments on a specific resource group or resource. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments` + -SubscriptionId ` + [-RoleNames ] ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + ``` + + Example 1: List all permanent assignments at subscription level with 'Contributor' and 'Owner' roles. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -DoNotOpenOutputFolder + ``` + + Example 2: List all permanent assignments at 'DemoRG' resource group level with 'Contributor' role. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor" ` + -ResourceGroupName "DemoRG" ` + -DoNotOpenOutputFolder + ``` + Example 3: List all permanent assignments at resource level with 'Contributor' and 'Owner' role. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + -DoNotOpenOutputFolder + ``` + + 3.

List PIM assignments (-ListPIMAssignments)

+ + Use this command to list Azure role with PIM assignments at the specified scope. By default, it lists all role assignments in the selected Azure subscription. Use respective parameters to list assignments for a specific role, or to list assignments on a specific resource group or resource. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -SubscriptionId ` + [-RoleNames ] ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + ``` + Example 1: List 'Contributor' and 'Owner' PIM assignments at subscription level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -DoNotOpenOutputFolder + ``` + + Example 2: List 'Contributor' PIM assignments at 'DemoRG' resource group level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor" ` + -ResourceGroupName "DemoRG" ` + -DoNotOpenOutputFolder + ``` + Example 3: List 'Contributor' and 'Owner' PIM assignments at resource level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + -DoNotOpenOutputFolder + ``` +3.

List expiring assignments (-ListSoonToExpireAssignments)

+ + Use this command to list Azure role with PIM assignments at the specified scope that are about to expire in given number of days. Use respective parameters to list expiring assignments for a specific role on a subscription or a resource group or a resource. + + ```PowerShell + Get-AzSKPIMConfiguration -ListSoonToExpireAssignment ` + -SubscriptionId ` + -RoleNames ` + -ExpiringInDays ` # The number of days you want to query expiring assignments for + [-DoNotOpenOutputFolder] + ``` + Example 1: List 'Owner' PIM assignments at subscription level that will expire in 10 days. + + ```PowerShell + Get-AzSKPIMConfiguration -ListSoonToExpireAssignment ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames 'Owner' ` + -ExpiringInDays 10` + -DoNotOpenOutputFolder + +4.

List existing role settings (-ListRoleSettings)

+ + Use this command to list Azure role with PIM assignments at the specified scope to fetch existing settings of a role for both Eligible and Active role assignments. + + ```PowerShell + Get-AzSKPIMConfiguration -ListRoleSettings ` + -SubscriptionId ` + -RoleName "Owner" ` + [-ResourceGroupName] + [-ResourceName] + ``` + Example 1: List role settings for 'Owner' PIM role at subscription level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListRoleSettings ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + ``` + Example 2: List role settings for 'Contributor' PIM role at resource level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListRoleSettings ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Contributor" ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + ``` + +### Use Set-AzSKPIMConfiguration (alias 'setpim') for configuring/changing PIM settings at Subscription scope: + + 1.

Assigning users to roles (-AssignRole)

+ + Use this command to assign PIM role to the specified principal, at the specified scope. + > NOTE: + > a. You must have owner access to run this command. + > b. Assignment Type 'Eligible' or 'Active' can be provided in -AssignmentType parameter. If parameter is not explicitly used then role is assigned for 'Eligible' assignment type. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -SubscriptionId ` + -DurationInDays ` + -RoleName ` + -PrincipalName ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-AssignmentType ] ` + [-DoNotOpenOutputFolder] + ``` + Example 1: Grant PIM Eligible access with 'Contributor' role to a user for 30 days on a subscription. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -DurationInDays 30 ` + -RoleName "Contributor" ` + -PrincipalName "john.brown@microsoft.com" ` + -DoNotOpenOutputFolder + ``` + Example 2: Grant PIM Eligible access with 'Owner' role to a user for 20 days on a resource group 'DemoRG'. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -DurationInDays 20 ` + -ResourceGroupName "DemoRG" ` + -RoleName "Owner" ` + -PrincipalName "john.brown@microsoft.com" ` + -DoNotOpenOutputFolder + ``` + + Example 3: Grant PIM Eligible access with 'Owner' role to a user for 30 days on a resource 'AppServiceDemo'. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -DurationInDays 30 ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + -RoleName "Owner" ` + -PrincipalName "john.brown@microsoft.com" ` + -DoNotOpenOutputFolder + ``` + Example 4: Grant PIM Active access with 'Reader' role to a user for 30 days on a resource 'AppServiceDemo'. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -DurationInDays 30 ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + -RoleName "Reader" ` + -PrincipalName "john.brown@microsoft.com" ` + -AssignmentType "Active" ` + -DoNotOpenOutputFolder + ``` + + 2.

Activating your roles (-ActivateMyRole)

+ + Use this command to activate your PIM access. + + > NOTE: + > a. Activation duration should range between 1 to 8 hours. + > b. Make sure that the PIM role you are activating is eligible. If your PIM role has expired, contact subscription administrator to renew/re-assign your PIM role. + + ```PowerShell + Set-AzSKPIMConfiguration -ActivateMyRole ` + -SubscriptionId ` + -RoleName ` + -DurationInHours ` + -Justification ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + ``` + + Example 1: Activate your PIM access on a resource group. + + ```PowerShell + Set-AzSKPIMConfiguration -ActivateMyRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + -DurationInHours 8 ` + -Justification "Add a valid justification for enabling PIM role" ` + -ResourceGroupName "DemoRG" ` + -DoNotOpenOutputFolder + ``` + + 3.

Deactivating your roles (-DeactivateMyRole)

+ + Use this command to deactivate your PIM access. + + ```PowerShell + Set-AzSKPIMConfiguration -DeactivateMyRole ` + -SubscriptionId ` + -RoleName ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + ``` + Example 1: Deactivate your PIM access on a subscription. + + ```PowerShell + Set-AzSKPIMConfiguration -DeactivateMyRole ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + -DoNotOpenOutputFolder + ``` + + 4.

Assign PIM to permanent assignments at subscription/RG scope (-AssignEligibleforPermanentAssignments)

+ + Use this command to change permanent assignments to PIM for specified roles, at the specified scope. + + > NOTE: + > This command will create PIM, but will not remove the permanent assignments. After converting permanent assignments to PIM, you can use *"Set-AzSKPIMConfiguration -RemovePermanentAssignments"* command with *"-RemoveAssignmentFor MatchingEligibleAssignments"* parameter to remove permanent assignment. + + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + -SubscriptionId ` + -RoleNames ` + -DurationInDays ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + [-Force] + ``` + + Example 1: Convert permanent assignments to PIM for 'Contributor' and 'Owner' roles at subscription level . This command runs in an interactive manner so that you get an opportunity to verify the accounts being converted. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -DurationInDays 30 ` + -DoNotOpenOutputFolder + ``` + Example 2: Use *'-Force'* parameter to convert permanent assignments to PIM without giving runtime verification step. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo"` + -DurationInDays 20 ` + -DoNotOpenOutputFolder + -Force + ``` + + 5.

Removing permanent assignments altogether (-RemovePermanentAssignments)

+ + Use this command to remove permanent assignments of specified roles, at the specified scope. + + There are two options with this command: + + a. *-RemoveAssignmentFor MatchingEligibleAssignments (Default)*: Remove only those permanent roles which have a corresponding eligible PIM role. + + b. *-RemoveAssignmentFor AllExceptMe*: Remove all permanent role except your access. + + > NOTE: + > This command will *not* remove your permanent assignment if one exists. + + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -SubscriptionId ` + -RoleNames ` + [-RemoveAssignmentFor MatchingEligibleAssignments] ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + [-Force] + ``` + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -SubscriptionId ` + -RoleNames ` + [-RemoveAssignmentFor AllExceptMe] ` + [-ResourceGroupName ] ` + [-ResourceName ] ` + [-DoNotOpenOutputFolder] + [-Force] + + ``` + + Example 1: Remove 'Contributor' and 'Owner' roles that have permanent assignment at subscription level. This command runs in an interactive manner so that you get an opportunity to verify the accounts being removed. All the specified role with permanent access will get removed except your access. + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Contributor,Owner" ` + -RemoveAssignmentFor AllExceptMe + -DoNotOpenOutputFolder + ``` + + Example 2: Use *'-Force'* parameter to run the command in non-interactive mode. This will remove permanent assignment at resource level without giving runtime verification step. Use *-RoleNames* to filter the roles to be deleted. Here we have used *-RemoveAssignmentFor 'MatchingEligibleAssignments'*. Hence, this command deletes the specified role with permanent access only if there is a corresponding PIM role for the same. + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Owner" ` + -RemoveAssignmentFor MatchingEligibleAssignments + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo"` + -DoNotOpenOutputFolder + -Force + ``` + + + 6.

Extend PIM assignments for expiring assignments (-ExtendExpiringAssignments)

+ Use this command to extend PIM eligible assignments that are about to expire in n days + + Example 1: Extend Owner PIM roles that are to be expired in 10 days. This command runs in an interactive manner in order to verify the assignments being extended. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -DurationInDays 30 # The duration in days for expiration to be extended by + -DoNotOpenOutputFolder + ``` + + Example 2: Use *'-Force'* parameter to run the command in non-interactive mode. This command will extend expiry of 'Owner' PIM roles that are about to be expired in 10 days by skipping the verification step. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -DurationInDays 30 # The duration in days for expiration to be extended by + -Force + + Example 3: Extend Owner PIM roles that are to be expired in 10 days specific to principal names. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -PrincipalNames "abc@microsoft.com,def@microsoft.com" + + +7.

Configure role settings for role on an Azure resource (-ConfigureRoleSettings)

+ Use this command to configure a PIM role settings like maximum role assignment duration on a resource, mfa requirement upon activation etc. + + The command currently supports configuring the following settings: + + a. *For Eligible Assignment Type*: Maximum assignment duration, maximum activation duration, requirement of justification upon activation, requirement of mfa upon activation and applying conditional access policies during activation. + + b. *For Active Assignment Type*: Maximum active assignment duration, requirement of justification on assignment, requirement of mfa on assignment. + + + Example 1: Configure 'Owner' PIM role on a subscription for Eligible assignment type, to let maximum activation duration be 12 hours. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Owner" ` + -MaximumActivationDuration 12` + -ExpireEligibleAssignmentsInDays 90 ` + -RequireJustificationOnActivation $true + -RequireMFAOnActivation $true + -DoNotOpenOutputFolder` + ``` + + Example 2: Configure 'Owner' PIM role on a subscription for Eligible assignment type, to apply conditional access policy while activation. + Note: Currently application of both MFA and conditional policy on the same role is not supported. Either of them should be applied to a given role. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Owner" ` + -ApplyConditionalAccessPolicyForRoleActivation $true + -DoNotOpenOutputFolder` + ``` + + Example 3: Configure 'Reader' PIM role on a subscription for Active assignment type, to let maximum assignment duration be 15 days. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleNames "Reader" ` + -ExpireActiveAssignmentsInDays 15 ` + -RequireJustificationOnActiveAssignment $false ` + -RequireMFAOnActiveAssignment $true ` + -DoNotOpenOutputFolder + ``` +8.

Remove PIM assignments for a role on an Azure resource (-RemovePIMAssignment)

+ Use this command to remove PIM assignments of specified role, at the specified scope. + + Example 1: Remove 'Contributor' role that have PIM assignment at subscription level. This command runs in an interactive manner so that you get an opportunity to verify the accounts being removed. All the specified principal names with PIM access on the role will get removed. + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePIMAssignment ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Contributor" ` + -PrincipalNames "abc@microsoft.com,def@microsoft.com" + ``` + + Example 2: Use *'-Force'* parameter to run the command in non-interactive mode. This will remove PIM assignment at resource level without giving runtime verification step. + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePIMAssignment ` + -SubscriptionId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Contributor" ` + -PrincipalNames "abc@microsoft.com,def@microsoft.com" ` + -ResourceGroupName "DemoRG" ` + -ResourceName "AppServiceDemo" ` + -Force + ``` + +### Use Get-AzSKPIMConfiguration (alias 'getpim') for querying various PIM settings/status at Management Group level + + 1.

List permanent assignments (-ListPermanentAssignments)

+ + Use this command to list Azure role with permanent assignments at the specified scope. By default, it lists all role assignments in the selected Azure Management Group. Use respective parameters to list assignments for a specific role, or to list assignments on a specific roles. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments` + -ManagementGroupId ` + [-RoleNames ] ` + [-DoNotOpenOutputFolder] + ``` + + Example 1: List all permanent assignments at Management Group level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments ` + -ManagementGroupId + ``` + Example 2: List all permanent assignments at Management Group level with 'Contributor' and 'Owner' roles. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPermanentAssignments ` + -ManagementGroupId ` + -RoleNames "Contributor,Owner" ` + -DoNotOpenOutputFolder + ``` + + + 2.

List PIM assignments (-ListPIMAssignments)

+ + Use this command to list Azure role with PIM assignments at the specified scope. By default, it lists all role assignments in the selected Azure Management Group. Use respective parameters to list assignments for a specific roles. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -ManagementGroupId ` + [-RoleNames ] ` + [-DoNotOpenOutputFolder] + ``` + Example 1: List PIM assignments at Management Group level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -ManagementGroupId + ``` + Example 2: List 'Contributor' and 'Owner' PIM assignments at Management Group level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListPIMAssignments ` + -ManagementGroupId ` + -RoleNames "Contributor,Owner" ` + -DoNotOpenOutputFolder + ``` + + + 3.

List expiring assignments (-ListSoonToExpireAssignments)

+ + Use this command to list Azure role with PIM assignments at the specified scope that are about to expire in given number of days. Use respective parameters to list expiring assignments for a specific role on a Management Group. + + ```PowerShell + Get-AzSKPIMConfiguration -ListSoonToExpireAssignment ` + -ManagementGroupId ` + -RoleNames ` + -ExpiringInDays ` # The number of days you want to query expiring assignments for + [-DoNotOpenOutputFolder] + ``` + Example 1: List 'Owner' PIM assignments at Management Group level that will expire in 10 days. + + ```PowerShell + Get-AzSKPIMConfiguration -ListSoonToExpireAssignment ` + -ManagementGroupId ` + -RoleNames 'Owner' ` + -ExpiringInDays 10` + -DoNotOpenOutputFolder + ``` + 4.

List existing role settings (-ListRoleSettings)

+ + Use this command to list Azure role with PIM assignments at the specified scope to fetch existing settings of a role for both Eligible and Active role assignments. + + ```PowerShell + Get-AzSKPIMConfiguration -ListRoleSettings ` + -ManagementGroupId ` + -RoleName "Owner" ` + ``` + Example 1: List role settings for 'Owner' PIM role at Management Group level. + + ```PowerShell + Get-AzSKPIMConfiguration -ListRoleSettings ` + -ManagementGroupId "65be5555-34ee-43a0-ddee-23fbbccdee45" ` + -RoleName "Owner" ` + ``` + +### Use Set-AzSKPIMConfiguration (alias 'setpim') for configuring/changing PIM settings at Management Group level: + + 1.

Assigning users to roles (-AssignRole)

+ + Use this command to assign PIM role to the specified principal, at the specified scope. + > NOTE: + > You must have owner access to run this command. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -ManagementGroupId ` + -DurationInDays ` + -RoleName ` + -PrincipalNames ` + [-DoNotOpenOutputFolder] + ``` + Example 1: Grant PIM access with 'Contributor' role to a user for 30 days on a Management Group. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignRole ` + -ManagementGroupId ` + -DurationInDays 30 ` + -RoleName "Contributor" ` + -PrincipalName "john.brown@microsoft.com" ` + -DoNotOpenOutputFolder + ``` + + 2.

Activating your roles (-ActivateMyRole)

+ + Use this command to activate your PIM access. + + > NOTE: + > a. Activation duration should range between 1 to 8 hours. + > b. Make sure that the PIM role you are activating is eligible. If your PIM role has expired, contact subscription administrator to renew/re-assign your PIM role. + + ```PowerShell + Set-AzSKPIMConfiguration -ActivateMyRole ` + -ManagementGroupId ` + -RoleName ` + -DurationInHours ` + -Justification ` + [-DoNotOpenOutputFolder] + ``` + + Example 1: Activate your PIM access on a Management Group. + + ```PowerShell + Set-AzSKPIMConfiguration -ActivateMyRole ` + -ManagementGroupId ` + -RoleName "Owner" ` + -DurationInHours 8 ` + -Justification "Add a valid justification for enabling PIM role" ` + -DoNotOpenOutputFolder + ``` + + 3.

Deactivating your roles (-DeactivateMyRole)

+ + Use this command to deactivate your PIM access. + + ```PowerShell + Set-AzSKPIMConfiguration -DeactivateMyRole ` + -ManagementGroupId ` + -RoleName ` + [-DoNotOpenOutputFolder] + ``` + Example 1: Deactivate your PIM access on a subscription. + + ```PowerShell + Set-AzSKPIMConfiguration -DeactivateMyRole ` + -ManagementGroupId ` + -RoleName "Owner" ` + -DoNotOpenOutputFolder + ``` + + 4.

Assign PIM to permanent assignments at Management Group scope (-AssignEligibleforPermanentAssignments)

+ + Use this command to change permanent assignments to PIM for specified roles, at the specified scope. + + > NOTE: + > This command will create PIM, but will not remove the permanent assignments. After converting permanent assignments to PIM, you can use *"Set-AzSKPIMConfiguration -RemovePermanentAssignments"* command with *"-RemoveAssignmentFor MatchingEligibleAssignments"* parameter to remove permanent assignment. + + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + –ManagementGroupId ` + -RoleNames ` + -DurationInDays ` + [-DoNotOpenOutputFolder] + [-Force] + ``` + + Example 1: Convert permanent assignments to PIM for 'Contributor' and 'Owner' roles at Management Group level. This command runs in an interactive manner so that you get an opportunity to verify the accounts being converted. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + –ManagementGroupId ` + -RoleNames "Contributor,Owner" ` + -DurationInDays 30 ` + -DoNotOpenOutputFolder + ``` + + Example 2: Use '-Force' parameter to convert permanent assignments to PIM without giving runtime verification step. + + ```PowerShell + Set-AzSKPIMConfiguration -AssignEligibleforPermanentAssignments ` + –ManagementGroupId ` + -RoleNames "Contributor,Owner" ` + -DurationInDays 30 ` + -DoNotOpenOutputFolder ` + -Force + ``` + + 5.

Removing permanent assignments altogether (-RemovePermanentAssignments)

+ + Use this command to remove permanent assignments of specified roles, at the specified scope. + + There are two options with this command: + + a. *-RemoveAssignmentFor MatchingEligibleAssignments (Default)*: Remove only those permanent roles which have a corresponding eligible PIM role. + + b. *-RemoveAssignmentFor AllExceptMe*: Remove all permanent role except your access. + + > NOTE: + > This command will *not* remove your permanent assignment if one exists. + + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -ManagementGroupId ` + -RoleNames ` + [-RemoveAssignmentFor MatchingEligibleAssignments] ` + [-DoNotOpenOutputFolder] + [-Force] + ``` + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -ManagementGroupId ` + -RoleNames ` + [-RemoveAssignmentFor AllExceptMe] ` + [-DoNotOpenOutputFolder] + [-Force] + + ``` + + Example 1: Remove 'Contributor' and 'Owner' roles that have permanent assignment at Management Group level. This command runs in an interactive manner so that you get an opportunity to verify the accounts being removed. All the specified role with permanent access will get removed except your access. + + ```PowerShell + Set-AzSKPIMConfiguration -RemovePermanentAssignments ` + -ManagementGroupId ` + -RoleNames "Contributor,Owner" ` + -RemoveAssignmentFor AllExceptMe + -DoNotOpenOutputFolder + ``` + + + 6.

Extend PIM assignments for expiring assignments (-ExtendExpiringAssignments)

+ Use this command to extend PIM eligible assignments that are about to expire in n days + + Example 1: Extend Owner PIM roles that are to be expired in 10 days. This command runs in an interactive manner in order to verify the assignments being extended. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -ManagementGroupId ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -DurationInDays 30 # The duration in days for expiration to be extended by + -DoNotOpenOutputFolder + ``` + + Example 2: Use *'-Force'* parameter to run the command in non-interactive mode. This command will extend expiry of 'Owner' PIM roles that are about to be expired in 10 days by skipping the verification step. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -ManagementGroupId ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -DurationInDays 30 # The duration in days for expiration to be extended by + -Force + ``` + + Example 3: Extend Owner PIM roles that are to be expired in 10 days specific to principal names. + + ```PowerShell + Set-AzSKPIMConfiguration -ExtendExpiringAssignments ` + -ManagementGroupId ` + -RoleName "Owner" ` + -ExpiringInDays 10 + -PrincipalNames "abc@microsoft.com,def@microsoft.com" + ``` + +7.

Configure role settings for role on an Azure resource (-ConfigureRoleSettings)

+ Use this command to configure a PIM role settings like maximum role assignment duration on a resource, mfa requirement upon activation etc. + + The command currently supports configuring the following settings: + + a. *For Eligible Assignment Type*: Maximum assignment duration, maximum activation duration, requirement of justification upon activation, requirement of mfa upon activation and applying conditional access policies during activation. + + b. *For Active Assignment Type*: Maximum active assignment duration, requirement of justification on assignment, requirement of mfa on assignment. + + Example 1: Configure 'Owner' PIM role on a Management Group for Eligible assignment type, to let maximum activation duration be 12 hours. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -ManagementGroupId ` + -RoleNames "Owner" ` + -MaximumActivationDuration 12` + -ExpireEligibleAssignmentsInDays 90 ` + -RequireJustificationOnActivation $true + -RequireMFAOnActivation $true + -DoNotOpenOutputFolder` + ``` + + Example 2: Configure 'Owner' PIM role on a Management Group for Eligible assignment type, to apply conditional access policy while activation. + Note: Currently application of both MFA and conditional policy on the same role is not supported. Either of them should be applied to a given role. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -ManagementGroupId ` + -RoleNames "Owner" ` + -ApplyConditionalAccessPolicyForRoleActivation $true + -DoNotOpenOutputFolder` + ``` + Example 3: Configure 'Reader' PIM role on a Management Group for Active assignment type, to let maximum assignment duration be 15 days. + + ```PowerShell + Set-AzSKPIMConfiguration -ConfigureRoleSettings ` + -ManagementGroupId ` + -RoleNames "Reader" ` + -ExpireActiveAssignmentsInDays 15 ` + -RequireJustificationOnActiveAssignment $false ` + -RequireMFAOnActiveAssignment $true ` + -DoNotOpenOutputFolder + ``` + +## AzSK: Credential hygiene helper cmdlets + +To help avoid availability disruptions due to credential expiry, AzSK has introduced cmdlets that will help you track and get notified about important credentials across your subscription. AzSK now offers a register-and-track solution to help monitor the last update of your credentials. This will help you periodically track the health of your credentials which are nearing expiry/need rotation. + +AzSK has also introduced the concept of ‘credential groups’ wherein a set of credentials belonging to a specific application/functionality can be tracked together for expiry notifications. + +NOTE: + Ensure you have atleast 'Contributor' access on the subscription before running the below helper commands. To configure expiry notifications for the tracked credentials, ensure you have 'Owner' access on the subscription. + +### Use New-AzSKTrackedCredential to onboard a credential for tracking + +```PowerShell + New-AzSKTrackedCredential -SubscriptionId '' ` + -CredentialName '' ` + -CredentialLocation '' ` + -RotationIntervalInDays ` + -NextExpiryInDays ` + [-CredentialGroup ''] ` + -Comment '' +``` +|Param Name|Purpose|Required?|Allowed Values| +|----|----|----|----| +|SubscriptionId|Subscription ID of the Azure subscription in which the to-be-tracked credential resides.|TRUE|None| +|CredentialName|Friendly name for the credential.|TRUE|None| +|CredentialLocation|Host location of the credential.|TRUE|Custom/AppService/KeyVault| +|RotationIntervalInDays|Time in days before which the credential needs an update.|TRUE|Integer| +|NextExpiryInDays|Time in days for the next expiry of the credential.|TRUE|Integer| +|CredentialGroup|(Optional) Name of the action group to be used for expiry notifications|FALSE|Valid action group name.| +|Comment|Comment to capture more information about the credential for the user for future tracking purposes.|TRUE|None| + +> NOTE 1: + > For credential location type 'AppService', you will have to provide app service name, resource group, app config type (app setting/connection string) & app config name. Make sure you have the required access on the resource. + +> NOTE 2: + > For credential location type 'KeyVault', you will have to provide key vault name, credential type (key/secret) & credential name. Make sure you have the required access on the resource. + +> NOTE 3: + > Use credential location type 'Custom', if the credential doesn't belong to an appservice or key vault. + +### Use Get-AzSKTrackedCredential to list the onboarded credential(s) + +```PowerShell + Get-AzSKTrackedCredential -SubscriptionId '' [-CredentialName ''] [-DetailedView] +``` +> NOTE: + > Not providing credential name will list all the AzSK-tracked credentials in the subscription. Use '-DetailedView' flag to list down detailed metadata about the credentials. + +### Use Update-AzSKTrackedCredential to update the credential settings and reset the last updated timestamp + +```PowerShell + Update-AzSKTrackedCredential -SubscriptionId '' ` + -CredentialName '' ` + [-RotationIntervalInDays ] ` + [-CredentialGroup ''] ` + [-ResetLastUpdate] ` + -Comment '' +``` + +> NOTE: + > Use '-ResetLastUpdate' to reset the last update time to current timestamp. + +### Use Remove-AzSKTrackedCredential to deboard a credential from AzSK tracking + +```PowerShell + Remove-AzSKTrackedCredential -SubscriptionId '' [-CredentialName ''] [-Force] +``` +### Use New-AzSKTrackedCredentialGroup to configure email alerts to notify users about AzSK-tracked credentials that are about to expire (<= 7 days) or have already expired. + +```PowerShell + New-AzSKTrackedCredentialGroup -SubscriptionId '' -AlertEmail '' +``` diff --git a/02-Secure-Development/ControlCoverage/Feature/APIConnection.md b/02-Secure-Development/ControlCoverage/Feature/APIConnection.md new file mode 100644 index 00000000..172860a5 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/APIConnection.md @@ -0,0 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

APIConnection

Description & RationaleControlSeverityAutomatedFix Script
Logic App connectors must use AAD-based authentication wherever possible
Using the native enterprise directory for authentication ensures that there is a built-in high level of assurance in the user identity established for subsequent access control. All Enterprise subscriptions are automatically associated with their enterprise directory (xxx.onmicrosoft.com) and users in the native directory are trusted for authentication to enterprise subscriptions.
HighYesNo
Data transit across connectors must use encrypted channel
Use of HTTPS ensures server/service authentication and protects data in transit from network layer man-in-the-middle, eavesdropping, session-hijacking attacks.
HighYesNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/APIManagement.md b/02-Secure-Development/ControlCoverage/Feature/APIManagement.md new file mode 100644 index 00000000..414fd837 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/APIManagement.md @@ -0,0 +1,12 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

APIManagement

+
Description & RationaleControlSeverityAutomated
All users/identities must be granted minimum required permissions using Role Based Access Control (RBAC)
Granting minimum access by leveraging RBAC feature ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
MediumYes
Metric alert rules must be configured for critical actions on API Management service
Metric alert for occurrence of unauthorized gateway requests help the admin to identify security breach attempts.
MediumYes
Diagnostics logs must be enabled with a retention period of at least 365 days
Logs should be retained for a long enough period so that activity trail can be recreated when investigations are required in the event of an incident or a compromise. A period of 1 year is typical for several compliance requirements as well.
MediumYes
Backend API must only be accessible over HTTPS via API Management service
Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks.
HighYes
API Management service instance should be backed up periodically
The service 'backup and restore' feature provides facility to recover from availability problems affecting the region where your API Management service is hosted.
MediumNo
'Named Values' that contain sensitive data must be encrypted by marking as 'secret'
Encrypted 'Named Values' are stored securely by the Azure platform.
HighYes
Ensure that only the most secure and up to date version of TLS is enabled on the API gateway
TLS 1.2 is the latest and most secure protocol. Using 3DES Ciphers, TLS protocols (1.1 and 1.0) and SSL 3.0 exposes the API to meet-in-the-middle attack, chosen-plaintext or known-plaintext attacks.
HighNo
Delete the two sample products 'Starter' and 'Unlimited' to avoid accidental exposure of APIs
By default, each API Management instance comes with two sample products: Starter and Unlimited. Unless the access control of these sample products is being strictly regulated, associating APIs to these products stands the chance of exposing APIs to unauthenticated users.
MediumYes
Any header containing sensitive data such as authorization token should not be logged in Application Insights
APIM provides an option to log request and response headers in Application Insights. Any header containing sensitive data such as authorization token should not be logged. This minimizes the risk of data loss from physical theft and also helps meet regulatory compliance requirements.
MediumYes
Ensure that CORS access is granted to a minimal set of trusted origins and only required verbs are supported
CORS enables an operation or an API to allow cross-domain calls from browser-based clients. Using '*' (allow all) for CORS setting means that all cross-origin requests are allowed. Restricting allowed origins to the specific set that needs access aligns with the principle of least privilege.
MediumYes
If delegated authentication is enabled, ensure that it is implemented securely
Delegation allows you to use your existing website for handling developer sign-in/sign-up and subscription to products as opposed to using the built-in functionality in the developer portal. It is the API publisher's responsibility to ensure protection of user data.
HighYes
Consider hosting APIM within a virtual network for improved isolation
Azure Virtual Network (VNet) deployment provides enhanced security and isolation for API management instance, as well as backend service, access control policies, and other features to further restrict access.
MediumYes
Custom domain with SSL binding must be configured for Proxy and Portal endpoints of Azure API Management instance
Use of custom domain protects a backend service from common attacks such as phishing, session hijacking and other DNS-related attacks.
MediumNo
Ensure that JWT validation is enabled if using OAuth 2.0 or OpenID connect
If 'validate-jwt' policy is not configured, client can call the API without the OAuth/OpenID connect authorization token. This policy enforces existence and validity of a JWT extracted from either a specified HTTP Header or a specified query parameter.
HighYes
Use Restrict caller IPs policies for additional protection
Using the IP filter policy feature ensures that access to the backend service is restricted to a specific set/group of clients. While this may not be feasible in all scenarios, when it can be used, it provides an extra layer of access control protection for critical assets.
MediumYes
Do not use API Management REST API
The credentials used to access API Management REST API provide admin-level access without support for role-based access control and without recording audit logs. For better security it is recommended to make calls through the ARM-based REST API
HighYes
Ensure that either OAuth 2.0 or OpenID Connect are used to authorize developer accounts in API Management
Enabling OAuth/OpenID connect user authorization ensure that only valid users have access, and they can only access resources to which they are entitled.
HighYes
Enterprise applications using APIM must authenticate developers/applications using Azure Active Directory backed credentials
Using the native enterprise directory for authentication ensures that there is a built-in high level of assurance in the user identity established for subsequent access control. All Enterprise subscriptions are automatically associated with their enterprise directory (xxx.onmicrosoft.com) and users in the native directory are trusted for authentication to enterprise subscriptions.
HighYes
Use transform policies to hide backend/implentation details in API responses
Information such as technology stack that is running on the backend and the original URLs that appear in the body of API's HTTP response are private backend info and should be hidden from external customers.
MediumNo
Do not include secrets directly in API configuration and policies
When using Git to save and configure your API Management service configuration, any secrets that are not defined as properties will be stored in the repository and will remain in its history until you disable and re-enable Git access. Properties (Named values) provide a secure place to manage constant string values, including secrets, across all API configuration and policies, so you don't have to store them directly in your policy statements.
HighYes
Use client certificates for authentication between gateway and backend APIs
Use client certificates to secure access to the back-end service of an API and protects data in transit from network layer man-in-the-middle, eavesdropping, session-hijacking attacks.
HighYes
'Requires Subscription' option must be turned on for all products in an API Management instance
When publishing APIs through Azure API Management (APIM), the easiest and most common way to secure access to the APIs is by using Subscription Keys. To obtain a Subscription Key for accessing APIs, a Subscription is required. This ensures that a Client applications that need to consume the published APIs must subscribe before making calls to those APIs.
HighYes
Critical APIs must not be exposed to Guest users
Guest users or unauthenticated developer portal users, such as prospective customers visiting the developer portal of an API Management instance can be granted certain read-only access, such as the ability to view APIs but not call them.
MediumYes
Use Managed Service Identity (MSI) for accessing other AAD-protected resources from the API management instance
Managed Service Identity (MSI) allows your API Management instance to easily access other AAD-protected resources, such as Azure Key Vault. The identity is managed by the Azure platform and eliminates the need to provision/manage/rotate any secrets thus reducing the overall risk.
MediumYes
Use the 'Requires Approval' option for APIs where additional checks/manual review is necessary
Enabling 'Requires Approval' ensures that only users approved by API publisher can subscribe to a product.
HighNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md b/02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md index ea62116b..2921e35b 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md and b/02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/AlertList.md b/02-Secure-Development/ControlCoverage/Feature/AlertList.md index 06148a89..81108d41 100644 --- a/02-Secure-Development/ControlCoverage/Feature/AlertList.md +++ b/02-Secure-Development/ControlCoverage/Feature/AlertList.md @@ -1 +1,196 @@ -

AzSDK Alerts List

+## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +

AzSK Alerts List

+

Mandatory Alerts

+
Alert NameDescriptionOperation List
AzSDK_SQL_Alert Alerts for SQLMicrosoft.Sql/servers/administrators/write
Microsoft.Sql/servers/administrators/delete
Microsoft.Sql/servers/firewallRules/write
Microsoft.Sql/servers/firewallRules/delete
Microsoft.Sql/servers/elasticPools/delete
Microsoft.Sql/servers/databases/delete
Microsoft.Sql/servers/databases/replicationLinks/delete
Microsoft.Sql/servers/databases/replicationLinks/unlink/action
Microsoft.Sql/servers/databases/dataMaskingPolicies/write
Microsoft.Sql/servers/databases/dataMaskingPolicies/rules/delete
Microsoft.Sql/servers/databases/dataMaskingPolicies/rules/write
Microsoft.Sql/servers/databases/connectionPolicies/write
Microsoft.Sql/servers/databases/transparentDataEncryption/write
Microsoft.Sql/servers/databases/auditingPolicies/write
AzSDK_Services_Alert Alerts for Azure ServicesMicrosoft.ServiceBus/namespaces/authorizationRules/write
Microsoft.ServiceBus/namespaces/authorizationRules/delete
Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action
Microsoft.ServiceBus/namespaces/queues/Delete
Microsoft.ServiceBus/namespaces/queues/authorizationRules/write
Microsoft.ServiceBus/namespaces/queues/authorizationRules/delete
Microsoft.ServiceBus/namespaces/queues/authorizationRules/listkeys/action
Microsoft.ServiceBus/namespaces/topics/Delete
Microsoft.ServiceBus/namespaces/topics/authorizationRules/write
Microsoft.ServiceBus/namespaces/topics/authorizationRules/delete
Microsoft.ServiceBus/namespaces/topics/authorizationRules/listkeys/action
Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete
Microsoft.DataLakeStore/accounts/delete
Microsoft.DataLakeStore/accounts/firewallRules/write
Microsoft.DataLakeAnalytics/accounts/delete
Microsoft.DataLakeAnalytics/accounts/storageAccounts/delete
Microsoft.DataLakeAnalytics/accounts/dataLakeStoreAccounts/delete
AzSDK_Subscription_Alert Alerts for Subscription ActivitiesMicrosoft.Authorization/elevateAccess/action
Microsoft.Authorization/classicAdministrators/write
Microsoft.Authorization/classicAdministrators/delete
Microsoft.Authorization/locks/write
Microsoft.Authorization/locks/delete
Microsoft.Authorization/policyAssignments/delete
Microsoft.Authorization/policyAssignments/write
Microsoft.Authorization/policyDefinitions/delete
Microsoft.Authorization/roleAssignments/write
Microsoft.Authorization/roleAssignments/delete
AzSDK_Network_Alert Alerts for NetworkMicrosoft.Network/dnszones/write
Microsoft.Network/dnszones/delete
Microsoft.Network/dnszones/MX/write
Microsoft.Network/dnszones/MX/delete
Microsoft.Network/dnszones/AAAA/write
Microsoft.Network/dnszones/AAAA/delete
Microsoft.Network/dnszones/CNAME/write
Microsoft.Network/dnszones/CNAME/delete
Microsoft.Network/dnszones/A/write
Microsoft.Network/dnszones/A/delete
Microsoft.Network/networkInterfaces/write
Microsoft.Network/networkInterfaces/join/action
Microsoft.Network/networkInterfaces/delete
Microsoft.Network/publicIPAddresses/delete
Microsoft.Network/virtualNetworks/write
Microsoft.Network/virtualNetworks/delete
Microsoft.Network/virtualNetworks/peer/action
Microsoft.Network/virtualNetworks/virtualNetworkPeerings/write
Microsoft.Network/virtualNetworks/virtualNetworkPeerings/delete
Microsoft.Network/virtualNetworks/subnets/write
Microsoft.Network/virtualNetworks/subnets/delete
Microsoft.Network/virtualNetworks/subnets/join/action
Microsoft.Network/networkSecurityGroups/write
Microsoft.Network/networkSecurityGroups/delete
Microsoft.Network/networkSecurityGroups/join/action
Microsoft.Network/networkSecurityGroups/securityRules/write
Microsoft.Network/networkSecurityGroups/securityRules/delete
Microsoft.Network/routeTables/write
Microsoft.Network/routeTables/delete
Microsoft.Network/routeTables/join/action
Microsoft.Network/routeTables/routes/write
Microsoft.Network/routeTables/routes/delete
Microsoft.Network/loadBalancers/inboundNatRules/write
AzSDK_Web_Alert Alerts for Web Microsoft.Web/sites/Delete
Microsoft.Web/sites/slotsswap/Action
Microsoft.Web/sites/applySlotConfig/Action
Microsoft.Web/sites/slots/config/Write
Microsoft.Web/sites/slots/config/list/Action
Microsoft.Web/sites/config/Write
Microsoft.Web/sites/config/list/Action
Microsoft.Web/sites/functions/listSecrets/Action
Microsoft.Web/certificates/Write
Microsoft.Web/certificates/Delete
AzSDK_KeyVault_Alert Alerts for KeyVaultMicrosoft.KeyVault/vaults/write
Microsoft.KeyVault/vaults/delete
Microsoft.KeyVault/vaults/deploy/action
Microsoft.KeyVault/vaults/secrets/read
Microsoft.KeyVault/vaults/secrets/write
AzSDK_Storage_Alert Alerts for Storage AccountMicrosoft.Storage/storageAccounts/delete
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Alert NameDescriptionOperation List
AzSK_Subscription_AlertAlerts for Subscription ActivitiesMicrosoft.Authorization/elevateAccess/action
Microsoft.Authorization/classicAdministrators/write
+ Microsoft.Authorization/classicAdministrators/delete
Microsoft.Authorization/locks/write
+ Microsoft.Authorization/locks/delete
Microsoft.Authorization/policyAssignments/delete
+ Microsoft.Authorization/policyAssignments/write
Microsoft.Authorization/policyDefinitions/delete
+ Microsoft.Authorization/roleAssignments/write
Microsoft.Authorization/roleAssignments/delete
+ Microsoft.Insights/ActivityLogAlerts/Delete
Microsoft.Insights/ActivityLogAlerts/Write
+ Microsoft.Insights/ActionGroups/Write
Microsoft.Insights/ActionGroups/Delete
AzSK_Storage_AlertAlerts for Storage AccountMicrosoft.Storage/storageAccounts/delete
AzSK_Database_AlertAlerts for DatabaseMicrosoft.Sql/servers/administrators/write
Microsoft.Sql/servers/administrators/delete
+ Microsoft.Sql/servers/firewallRules/write
Microsoft.Sql/servers/firewallRules/delete
+ Microsoft.Sql/servers/elasticPools/delete
Microsoft.Sql/servers/databases/delete
AzSK_Networking_AlertAlerts for NetworkMicrosoft.Network/dnszones/write
Microsoft.Network/dnszones/delete
+ Microsoft.Network/dnszones/MX/write
Microsoft.Network/dnszones/MX/delete
+ Microsoft.Network/dnszones/AAAA/write
Microsoft.Network/dnszones/AAAA/delete
+ Microsoft.Network/dnszones/CNAME/write
Microsoft.Network/dnszones/CNAME/delete
+ Microsoft.Network/dnszones/A/write
Microsoft.Network/dnszones/A/delete
+ Microsoft.Network/virtualNetworks/delete
AzSK_Security_AlertAlerts for KeyVaultMicrosoft.KeyVault/vaults/write
Microsoft.KeyVault/vaults/delete
+ Microsoft.KeyVault/vaults/secrets/write
AzSK_Analytics_AlertAlerts for AnalyticsMicrosoft.DataLakeAnalytics/accounts/delete
AzSK_Compute_AlertAlerts for ComputeMicrosoft.Compute/virtualMachines/delete
AzSK_Web_Alert_v2Alerts for WebMicrosoft.Web/sites/Delete
+ +

Optional Alerts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Alert NameDescriptionOperation List
AzSK_SQL_AlertAlerts for SQLMicrosoft.Sql/servers/administrators/write
Microsoft.Sql/servers/administrators/delete
+ Microsoft.Sql/servers/firewallRules/write
Microsoft.Sql/servers/firewallRules/delete
+ Microsoft.Sql/servers/elasticPools/delete
Microsoft.Sql/servers/databases/delete
+ Microsoft.Sql/servers/databases/replicationLinks/delete
+ Microsoft.Sql/servers/databases/replicationLinks/unlink/action
+ Microsoft.Sql/servers/databases/dataMaskingPolicies/write
+ Microsoft.Sql/servers/databases/dataMaskingPolicies/rules/delete
+ Microsoft.Sql/servers/databases/dataMaskingPolicies/rules/write
+ Microsoft.Sql/servers/databases/connectionPolicies/write
+ Microsoft.Sql/servers/databases/transparentDataEncryption/write
+ Microsoft.Sql/servers/databases/auditingPolicies/write
Microsoft.Sql/servers/virtualNetworkRules/write +
Microsoft.Sql/servers/virtualNetworkRules/delete
AzSK_Services_AlertAlerts for Azure ServicesMicrosoft.ServiceBus/namespaces/authorizationRules/write
+ Microsoft.ServiceBus/namespaces/authorizationRules/delete
+ Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action
+ Microsoft.ServiceBus/namespaces/queues/Delete
+ Microsoft.ServiceBus/namespaces/queues/authorizationRules/write
+ Microsoft.ServiceBus/namespaces/queues/authorizationRules/delete
+ Microsoft.ServiceBus/namespaces/queues/authorizationRules/listkeys/action
+ Microsoft.ServiceBus/namespaces/topics/Delete
+ Microsoft.ServiceBus/namespaces/topics/authorizationRules/write
+ Microsoft.ServiceBus/namespaces/topics/authorizationRules/delete
+ Microsoft.ServiceBus/namespaces/topics/authorizationRules/listkeys/action
+ Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete
Microsoft.DataLakeStore/accounts/delete +
Microsoft.DataLakeStore/accounts/firewallRules/write
Microsoft.DataLakeAnalytics/accounts/delete +
Microsoft.DataLakeAnalytics/accounts/storageAccounts/delete
+ Microsoft.DataLakeAnalytics/accounts/dataLakeStoreAccounts/delete
Microsoft.Compute/virtualMachines/write +
Microsoft.Compute/virtualMachines/delete
Microsoft.Compute/virtualMachines/extensions/write
+ Microsoft.Compute/virtualMachines/extensions/delete
Microsoft.Cache/redis/patchSchedules/delete
+ Microsoft.DocumentDB/databaseAccounts/listKeys/action
+ Microsoft.DocumentDB/databaseAccounts/regenerateKey/action
Microsoft.Cache/redis/regenerateKey/action +
Microsoft.Cache/redis/firewallRules/write
Microsoft.Cache/redis/firewallRules/delete
+ Microsoft.ContainerService/managedClusters/accessProfiles/listCredential/action
+ Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action
+ Microsoft.ContainerRegistry/registries/listCredentials/action
+ Microsoft.ContainerRegistry/registries/regenerateCredential/action
+ Microsoft.ContainerRegistry/locations/deleteVirtualNetworkOrSubnets/action
+ Microsoft.ContainerInstance/locations/deleteVirtualNetworkOrSubnets/action
+ Microsoft.HDInsight/clusters/updateGatewaySettings/action
+ Microsoft.HDInsight/clusters/configurations/action
Microsoft.HDInsight/clusters/applications/write
+ Microsoft.HDInsight/clusters/applications/delete
+ Microsoft.NotificationHubs/Namespaces/authorizationRules/write
+ Microsoft.NotificationHubs/Namespaces/NotificationHubs/authorizationRules/write
+ Microsoft.NotificationHubs/Namespaces/authorizationRules/listkeys/action
+ Microsoft.NotificationHubs/Namespaces/authorizationRules/regenerateKeys/action
+ Microsoft.NotificationHubs/Namespaces/NotificationHubs/authorizationRules/listkeys/action
+ Microsoft.NotificationHubs/Namespaces/NotificationHubs/authorizationRules/regenerateKeys/action
+ Microsoft.Cdn/profiles/GenerateSsoUri/action
+ Microsoft.Cdn/profiles/endpoints/customdomains/DisableCustomHttps/action
+ Microsoft.Automation/automationAccounts/agentRegistrationInformation/regenerateKey/action
+ Microsoft.ApiManagement/service/users/action
Microsoft.ApiManagement/service/groups/write
+ Microsoft.ApiManagement/service/groups/users/write
Microsoft.ApiManagement/service/users/write
+ Microsoft.ApiManagement/service/users/token/action
+ Microsoft.ApiManagement/service/users/generateSsoUrl/action
+ Microsoft.ApiManagement/service/getssotoken/action
+ Microsoft.ApiManagement/service/applynetworkconfigurationupdates/action
+ Microsoft.ApiManagement/service/tenant/regeneratePrimaryKey/action
+ Microsoft.ApiManagement/service/tenant/regenerateSecondaryKey/action
+ Microsoft.ApiManagement/service/products/policy/write
+ Microsoft.ApiManagement/service/products/policy/delete
+ Microsoft.ApiManagement/service/products/policies/write
+ Microsoft.ApiManagement/service/products/policies/delete
+ Microsoft.ApiManagement/service/subscriptions/regeneratePrimaryKey/action
+ Microsoft.ApiManagement/service/subscriptions/regenerateSecondaryKey/action
+ Microsoft.ApiManagement/service/apis/operations/policy/write
+ Microsoft.ApiManagement/service/apis/operations/policy/delete
+ Microsoft.ApiManagement/service/apis/operations/policies/write
+ Microsoft.ApiManagement/service/apis/operations/policies/delete
AzSK_Network_AlertAlerts for NetworkMicrosoft.Network/dnszones/write
Microsoft.Network/dnszones/delete
+ Microsoft.Network/dnszones/MX/write
Microsoft.Network/dnszones/MX/delete
+ Microsoft.Network/dnszones/AAAA/write
Microsoft.Network/dnszones/AAAA/delete
+ Microsoft.Network/dnszones/CNAME/write
Microsoft.Network/dnszones/CNAME/delete
+ Microsoft.Network/dnszones/A/write
Microsoft.Network/dnszones/A/delete
+ Microsoft.Network/networkInterfaces/write
Microsoft.Network/networkInterfaces/join/action
+ Microsoft.Network/networkInterfaces/delete
Microsoft.Network/publicIPAddresses/delete
+ Microsoft.Network/virtualNetworks/write
Microsoft.Network/virtualNetworks/delete
+ Microsoft.Network/virtualNetworks/peer/action
+ Microsoft.Network/virtualNetworks/virtualNetworkPeerings/write
+ Microsoft.Network/virtualNetworks/virtualNetworkPeerings/delete
+ Microsoft.Network/virtualNetworks/subnets/write
Microsoft.Network/virtualNetworks/subnets/delete
+ Microsoft.Network/virtualNetworks/subnets/join/action
Microsoft.Network/networkSecurityGroups/write +
Microsoft.Network/networkSecurityGroups/delete
Microsoft.Network/networkSecurityGroups/join/action +
Microsoft.Network/networkSecurityGroups/securityRules/write
+ Microsoft.Network/networkSecurityGroups/securityRules/delete
Microsoft.Network/routeTables/write
+ Microsoft.Network/routeTables/delete
Microsoft.Network/routeTables/join/action
+ Microsoft.Network/routeTables/routes/write
Microsoft.Network/routeTables/routes/delete
+ Microsoft.Network/loadBalancers/inboundNatRules/write
+ Microsoft.Network/trafficManagerProfiles/azureEndpoints/write
+ Microsoft.Network/trafficManagerProfiles/externalEndpoints/write
+ Microsoft.Network/trafficManagerProfiles/nestedEndpoints/write
AzSK_Web_AlertAlerts for Web Microsoft.Web/sites/Delete
Microsoft.Web/sites/slotsswap/Action
+ Microsoft.Web/sites/applySlotConfig/Action
Microsoft.Web/sites/slots/config/Write
+ Microsoft.Web/sites/slots/config/list/Action
Microsoft.Web/sites/config/Write
+ Microsoft.Web/sites/config/list/Action
Microsoft.Web/sites/functions/listSecrets/Action
+ Microsoft.Web/certificates/Write
Microsoft.Web/certificates/Delete
+ Microsoft.web/publishingusers/write
Microsoft.Web/sites/publishxml/Action
+ Microsoft.web/sites/virtualnetworkconnections/write
Microsoft.web/sites/virtualnetworkconnections/delete +
AzSK_KeyVault_AlertAlerts for KeyVaultMicrosoft.KeyVault/vaults/write
Microsoft.KeyVault/vaults/delete
+ Microsoft.KeyVault/vaults/deploy/action
Microsoft.KeyVault/vaults/secrets/read
+ Microsoft.KeyVault/vaults/secrets/write
diff --git a/02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md b/02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md index daeac610..c000a79b 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md and b/02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/AppService.md b/02-Secure-Development/ControlCoverage/Feature/AppService.md index ccf9a0cd..a9a5d88b 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/AppService.md and b/02-Secure-Development/ControlCoverage/Feature/AppService.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/ApplicationProxy.md b/02-Secure-Development/ControlCoverage/Feature/ApplicationProxy.md new file mode 100644 index 00000000..7ce96d35 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/ApplicationProxy.md @@ -0,0 +1,30 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +**Note:** You can scan your application proxy instance by executing [script](../Feature/Scripts/ADAppProxyScanScript.ps1.txt) in PowerShell. + + + + + +

ApplicationProxy

+ + + + + + + + + + +
Description & RationaleControlSeverityAutomatedFix Script
Only security compliant apps should be onboarded to AAD App Proxy +
AAD App proxy facilitates remote access to your on-prem apps. If these apps have not been designed and implemented securely, then security issues of your apps get exposed to the internet.
HighNoNo
AAD Authentication must be enabled as a pre-authentication method on your app +
Pre-authentication by its very nature, blocks a significant number of anonymous attacks, because only authenticated identities can access the back-end application.
HighNoNo
Delete personal data captured in logs on connector machine periodically or turn off connector machine logging if not required +
Connector machine logs may contain personal data. This needs to be handled with care and purged when not needed in keeping with good privacy principles.
HighNoNo
HTTP-Only cookie must be enabled while configuring App Proxy wherever possible +
Using an HTTP-Only cookie protects against cross site scripting (XSS) attacks by disallowing cookie access to client side scripts.
HighNoNo
Use a security hardened, locked down OS image for the connector machine +
The connector machine is serving as a 'gateway' into the corporate environment allowing internet based client endpoints access to enterprise data. Using a locked-down, secure baseline configuration ensures that this machine does not get leveraged as an entry point to attack the applications/corporate network.
HighNoNo
+ + + + diff --git a/02-Secure-Development/ControlCoverage/Feature/Automation.md b/02-Secure-Development/ControlCoverage/Feature/Automation.md index 3da3fd13..9547bce0 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/Automation.md and b/02-Secure-Development/ControlCoverage/Feature/Automation.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/AzSKCfg.md b/02-Secure-Development/ControlCoverage/Feature/AzSKCfg.md new file mode 100644 index 00000000..ebd948fc --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/AzSKCfg.md @@ -0,0 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

AzSKCfg

Description & RationaleControlSeverityAutomatedFix Script
Continuous Assurance automation account must be present in the subscription
Presence of CA ensures that regular scan is happening for your cloud subscription and resources.
HighYesNo
Continuous Assurance automation account must be in a healthy state
Presence of CA ensures that regular scan is happening for your cloud subscription and resources.
HighYesNo
AzSK scans must use latest version of the AzSK Module
With each release new security updates are being added. Using the latest AzSK module ensures that your cloud subscription and resources are scanned with the latest controls.
HighYesNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/Batch.md b/02-Secure-Development/ControlCoverage/Feature/Batch.md index 805abc9c..d80b936a 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/Batch.md and b/02-Secure-Development/ControlCoverage/Feature/Batch.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/BotService.md b/02-Secure-Development/ControlCoverage/Feature/BotService.md new file mode 100644 index 00000000..db5b4837 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/BotService.md @@ -0,0 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

BotService

Description & RationaleControlSeverityAutomatedFix Script
Bot Service API must only be accessible over HTTPS
Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks.
HighNoNo
Ensure to use own storage adapter instead of Bot Framework State Service API.
Using this feature ensures that sensitive data is stored encrypted at rest. This minimizes the risk of data loss from physical theft and also helps meet regulatory compliance requirements.
HighNoNo
Secrets in Bot Service must be handled properly.
Keeping secrets such as passwords, keys, etc. in clear text can lead to easy compromise at various avenues during an application's lifecycle.
HighNoNo
Make sure important activities and events during Bot interactions are logged.
Analytics can be useful to detect unusual usage behavior patterns.
MediumYesNo
Only specific/required channels must be configured to allow traffic to bot service.
Each channel enabled for the Bot exposes the bot to activity on that channel. If a channel that is not actually required is enabled for the bot, it introduces unnecessary avenues for attack.
HighYesNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/CDN.md b/02-Secure-Development/ControlCoverage/Feature/CDN.md index 7af77474..36a156b6 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/CDN.md and b/02-Secure-Development/ControlCoverage/Feature/CDN.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/CloudService.md b/02-Secure-Development/ControlCoverage/Feature/CloudService.md index 7a78feb5..e03e8a93 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/CloudService.md and b/02-Secure-Development/ControlCoverage/Feature/CloudService.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/ContainerInstances.md b/02-Secure-Development/ControlCoverage/Feature/ContainerInstances.md new file mode 100644 index 00000000..47bcb556 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/ContainerInstances.md @@ -0,0 +1,15 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

ContainerInstances

+ + + + + +
Description & RationaleControlSeverityAutomatedFix Script
Use of public IP address and ports should be carefully reviewed
Public IP address provides direct access over the internet exposing the container to all type of attacks over the public network.
HighYesNo
Make sure container images (including nested images) are from a trustworthy source
If a container runs an untrusted image (or an untrusted nested image), it can violate integrity of the infrastructure and lead to all types of security attacks.
HighYesNo
Make sure container images are hosted on a trustworthy registry that has strong authentication, authorization and data protection mechanisms
If a container image is served from an untrusted registry, the image itself may not be trustworthy. Running such a compromised image can lead to loss of sensitive enterprise data.
HighYesNo
A container group must contain only containers which trust each other
Containers hosted in the same container group can monitor traffic of other containers within the group and can also access the file system of the host OS. Hence a container group must not host containers which do not trust each other. In other words, do not mix containers across trust boundaries in the same group.
HighYesNo
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/ContainerRegistry.md b/02-Secure-Development/ControlCoverage/Feature/ContainerRegistry.md new file mode 100644 index 00000000..e12d9f3e --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/ContainerRegistry.md @@ -0,0 +1,101 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + + + +

ContainerRegistry

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description & RationaleControlSeverityAutomatedFix Script
Admin user in Container Registry must be disabled
The admin user is designed for a single + user to access the registry. All users authenticating with the admin account appear as a single user to + the registry. Admin users are having high privileged role increases the attack surface for the server + without being tracked. Using AAD based identity ensures that there is a built-in high level of + assurance in the user identity established for subsequent access control.
HighYesYes
Service principal identity should be used to access container images in Container Registry
Using + a 'user' account should be avoided because, in general, a user account will likely have broader set of + privileges to enterprise assets. Using a dedicated SPN ensures that the SPN does not have permissions + beyond the ones specifically granted for the given scenario.
MediumYesNo
Credentials of service principal used for Container Registry must be stored in Key Vault
Keeping/sharing + password in clear text can lead to easy compromise at various avenues during an application's life + cycle. Storing them in a key vault ensures that they are protected at rest.
HighNoNo
All users/identities must be granted minimum required permissions using Role Based Access Control + (RBAC)
Granting minimum access by leveraging RBAC feature ensures that users are granted + just enough permissions to perform their tasks. This minimizes exposure of the resources in case of + user/service account compromise.
MediumYesNo
Image vulnerability scan should be configured through webhook when images are pushed to Container + Registry
Container image(s) having vulnerability (e.g. missing OS patches in base image, + open ports in image) can lead to loss of sensitive enterprise data.
MediumYesNo
Container Registry must have latest/patched image(s) all the time
Un-patched images are + easy targets for compromise from various malware/trojan attacks that exploit known vulnerabilities in + operating systems and related software.
MediumNoNo
Content trust in Container Registry must be enabled
Content trust gives the ability to + verify both the integrity and the publisher of all the data received from a Registry over any channel. + If a container image is served from an untrusted registry, the image itself may not be + trustworthy/stable. Running such a compromised image can lead to loss of sensitive enterprise data.
MediumYesNo
Activity logs for Data Container Registry should be reviewed periodically
Periodic reviews + of activity and audit logs ensures that anomalous activity can be identified early enough instead of + after a major compromise.
MediumNoNo
Only signed images must be pushed in Container Registry
Content trust gives the ability to + verify both the integrity and the publisher of all the data received from a Registry over any channel. + If a container image is served from an untrusted registry, the image itself may not be + trustworthy/stable. Running such a compromised image can lead to loss of sensitive enterprise data.
MediumNoNo
+ +
+ + + diff --git a/02-Secure-Development/ControlCoverage/Feature/CosmosDB.md b/02-Secure-Development/ControlCoverage/Feature/CosmosDB.md index 65b99ef5..3f4ddb36 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/CosmosDB.md and b/02-Secure-Development/ControlCoverage/Feature/CosmosDB.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/DBForMySql.md b/02-Secure-Development/ControlCoverage/Feature/DBForMySql.md new file mode 100644 index 00000000..80e37f33 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/DBForMySql.md @@ -0,0 +1,12 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

DBForMySQL

+
Description & RationaleControlSeverityAutomated
Use the 'Allow access to Azure services' flag or IP range only if required
The 'Allow access to Azure services' setting configures a very broad range of IP addresses from Azure as permitted to access the MySQL Server. Please make sure your scenario really requires this setting before enabling it. Turning it ON exposes your MySQL Server to risk of attacks from resources (IPs) owned by others in the Azure region.
HighYes
Configure only the required IP addresses on MySQL server. Do not use 'Any-to-Any' IP range.
Using the firewall feature ensures that access to the data or the service is restricted to a specific set/group of clients. NOTE: While this control does provide an extra layer of access control protection, it may not always be feasible to implement in all scenarios.
HighYes
SSL connection must be enabled for Azure Database for MySQL
Enforcing SSL connections between your database server and your client applications helps protect against 'man in the middle' attacks by encrypting the data stream between the server and your application.
HighYes
Consider using virtual network rules for improved isolation
Virtual network rules provides isolation for your Azure Database for MySQL by permitting only the specified virtual networks to access the database server.
MediumYes
Backup and Disaster Recovery must be planned at the time of creation of Azure Database for MySql service
Azure Database for MySQL offers default backup/disaster recovery for 7 days that can be extended up to 35 days. You can choose between locally redundant or geo-redundant backup storage. When processing critical workloads, a team must have adequate backups of the data.
MediumYes
Advanced Threat Protection must be enabled for Azure Database for MySQL
Advanced Threat Protection for Azure Database for MySQL provides a layer of security, which enables customers to detect and respond to potential threats as they occur by providing security alerts on anomalous activities.
HighYes
Diagnostics logs must be enabled with a retention period of at least365 days.
Logs should be retained for a long enough period so that activity trail can be recreated when investigations are required in the event of an incident or a compromise. A period of 1 year is typical for several compliance requirements as well.
MediumYes
Diagnostic and activity logs for Azure Database for MySQL should be reviewed periodically
Periodic reviews of diagnostics, activity and audit logs ensures that anomalous activity can be identified early enough instead of after a major compromise.
MediumNo
Access to Azure Database for MySQL Servers must be granted in accordance with the principle of least privilege
Granting minimum access ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
HighNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/DBforPostgreSQL.md b/02-Secure-Development/ControlCoverage/Feature/DBforPostgreSQL.md new file mode 100644 index 00000000..44270125 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/DBforPostgreSQL.md @@ -0,0 +1,12 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

DBForPostgreSql

+
Description & RationaleControlSeverityAutomated
Access to Azure Database for PostgreSQL Servers must be granted in accordance with the principle of least privilege
Granting minimum access ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
HighNo
SSL connection must be enabled for Azure Database for PostgreSQL
Enforcing SSL connections between your database server and your client applications helps protect against 'man-in-the-middle' attacks by encrypting the data stream between the server and your application.
HighYes
Configure only the required IP addresses on PostgreSQL server. Do not use 'Any-to-Any' IP range 0.0.0.0 to 255.255.255.255
Using the firewall feature ensures that access to the data or the service is restricted to a specific set/group of clients. NOTE: While this control does provide an extra layer of access control protection, it may not always be feasible to implement in all scenarios.
HighYes
Use the 'Allow access to Azure services' flag only if required
The 'Allow access to Azure services' setting configures a very broad range of IP addresses from Azure as permitted to access the PostgreSQL Server. Please make sure your scenario really requires this setting before enabling it. Turning it ON exposes your PostgreSQL Server to risk of attacks from resources (IPs) owned by others in the Azure region.
HighYes
Backup and Disaster Recovery must be planned for the default Azure Database for PostgreSQL service
Azure Database for PostgreSQL offers backup/disaster recovery up to 35 days. It also provides the flexibility to choose between locally redundant or geo-redundant backup storage. When processing critical workloads, a team must have adequate backups of the data.
MediumYes
Advanced Threat Protection must be enabled for Azure Database for PostgreSQL
Advanced Threat Protection for Azure Database for PostgreSQL provides a layer of security, which enables customers to detect and respond to potential threats as they occur by providing security alerts on anomalous activities.
HighYes
Consider using virtual network rules for improved isolation
Virtual network rules provides isolation for your Azure Database for PostgreSQL by permitting only the specified virtual networks to access the database server.
MediumYes
Diagnostics logs must be enabled with a retention period of at least 365 days
Logs should be retained for a long enough period so that activity trail can be recreated when investigations are required in the event of an incident or a compromise. A period of 1 year is typical for several compliance requirements as well.
MediumYes
Diagnostic and activity logs for Azure Database for PostgreSQL should be reviewed periodically
Periodic reviews of diagnostics, activity and audit logs ensures that anomalous activity can be identified early enough instead of after a major compromise.
MediumNo
Enable PostgreSQL server parameters log_connections and log_disconnections
PostgreSQL sever logging parameters enable log collection of important system events pertinent to security. Regular monitoring of logs can help to detect any suspicious and malicious activity early and respond in a timely manner.
MediumYes
Ensure server parameter 'connection_throttling' is set to 'ON'
Connection throttling protects your server against password guessing and brute force attacks.
HighYes
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/DataFactory.md b/02-Secure-Development/ControlCoverage/Feature/DataFactory.md index 4747c143..9fcf14e1 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/DataFactory.md and b/02-Secure-Development/ControlCoverage/Feature/DataFactory.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/DataFactoryV2.md b/02-Secure-Development/ControlCoverage/Feature/DataFactoryV2.md new file mode 100644 index 00000000..435cb257 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/DataFactoryV2.md @@ -0,0 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

DataFactoryV2

Description & RationaleControlSeverityAutomated
User accounts/roles connecting to data source must have minimum required permissions
Granting minimum access ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
MediumNo
All linked service credentials should be stored in Key Vault.
Keeping secrets such as DB connection strings, passwords, keys, etc., in clear text can lead to easy compromise at various avenues during an application's lifecycle. Storing them in a key vault ensures that they are protected at rest.
MediumNo
Data factory must use a service identity for authenticating to supported linked services.
Using a service identity for authentication ensures that there is a built-in high level of assurance for subsequent access control.
MediumNo
Configure activity output as 'Secure Output' if the activity emits sensitive data.
Configuring activity output as 'Secure Output' prevents it from getting logged to monitoring.
MediumNo
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/DataLakeAnalytics.md b/02-Secure-Development/ControlCoverage/Feature/DataLakeAnalytics.md index f3aa354e..03bce3e8 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/DataLakeAnalytics.md and b/02-Secure-Development/ControlCoverage/Feature/DataLakeAnalytics.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/DataLakeStore.md b/02-Secure-Development/ControlCoverage/Feature/DataLakeStore.md index 4ba55b56..32f02a60 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/DataLakeStore.md and b/02-Secure-Development/ControlCoverage/Feature/DataLakeStore.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/Databricks.md b/02-Secure-Development/ControlCoverage/Feature/Databricks.md new file mode 100644 index 00000000..08b651a1 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/Databricks.md @@ -0,0 +1,11 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

Databricks

Description & RationaleControlSeverityAutomated
Secrets and keys must not be in plain text in notebooks and jobs
Keeping secrets such as connection strings, passwords, keys, etc. in clear text can lead to easy compromise. Storing them in a secert scope ensures that they are protected at rest.
MediumYes
Use Azure Key Vault backed secret scope to hold secrets
Using Key Vault backed secret scopes leads to imroved protection and segregation of stored secrets.
MediumYes
Each secret scope should use an independent key vault
Using a separate key vault for each secret scope leads to better segregation of access to secrets via use of scope level ACLs. If the same key vault is used for two different scopes then any person with access to either of them will be able to see keys and secrets in both.
MediumYes
Personal access tokens (PAT) must have a shortest possible validity period
If a personal access token (PAT) gets compromised, the Databricks assets accessible to the user can be accessed/manipulated by unauthorized users. Minimizing the validity period of the PAT ensures that the window of time available to an attacker in the event of compromise is small.
HighYes
All users/identities must be granted minimum required permissions using Role Based Access Control (RBAC)
Granting minimum access by leveraging RBAC feature ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user account compromise.
MediumYes
Minimize the number of workspace admins
Databricks workspace admins have full access on the workspace to perform any operation. Each additional person in the admin role increases the attack surface for the workspace. The number of members in these roles should be kept to as low as possible.
MediumYes
All users must be granted minimum required permissions on clusters
Granting minimum access by leveraging RBAC feature ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user account compromise.
MediumNo
Workspace access control should be enabled
Enabling workspace access control allows an admin to manage fine-grained user permissions and ensures that users can perform only intended operations. This minimizes exposure of data in case of user account compromise.
MediumYes
Cluster access control should be enabled
Enabling cluster access control allows admin to provide restricted access to user over cluster so that users can perform only intended operations. This minimizes exposure of data in case of user/service account compromise.
MediumYes
Job access control should be enabled
Enabling job access control ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of data in case of user/service account compromise.
MediumYes
Do not mount any data sources that may not be required for all users in the workspace.
Mouting a data source gives all users within the workspace access to the data from the mount point. Thus, mounting sources with sensitive data onto DBFS can lead to unauthorized access.
MediumNo
Guest accounts within the AAD tenant should not be granted admin access
Databricks workspace admins have full access on the workspace to perform any operation. Each guest account in an admin role increases the attack surface for the workspace. Adding guest accounts as admin on workspace should be avoided.
MediumYes
Use of any virtual network peerings should be justified
Resources in the peered virtual networks can communicate with each other directly. If the two peered networks are on different sides of a security boundary (e.g., corpnet v. private vNet), this can lead to exposure of corporate data. Hence any vNet peerings should be closely scrutinized and approved by the network security team
HighYes
+ +
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/ERvNet.md b/02-Secure-Development/ControlCoverage/Feature/ERvNet.md index 46d9bf0d..7264cedc 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/ERvNet.md and b/02-Secure-Development/ControlCoverage/Feature/ERvNet.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/EventHub.md b/02-Secure-Development/ControlCoverage/Feature/EventHub.md index 25b5b3c3..4fd7898f 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/EventHub.md and b/02-Secure-Development/ControlCoverage/Feature/EventHub.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/HDInsight.md b/02-Secure-Development/ControlCoverage/Feature/HDInsight.md new file mode 100644 index 00000000..2018fb35 --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/HDInsight.md @@ -0,0 +1,60 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

HDInsight

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description & RationaleControlSeverityAutomatedFix Script
HDInsight must have supported HDI cluster version +
Being on the latest/supported HDInsight version significantly reduces risks from security bugs or updates that may be present in older or retired cluster versions.
HighNoYes
Use Public-Private key pair together with a passcode for SSH login +
Public-Private key pair help to protect against password guessing and brute force attacks
HighNoNo
HDInsight cluster access must be restricted using virtual network or Azure VPN gateway service with NSG traffic rules +
Restricting cluster access with inbound and outbound traffic via NSGs limits the network exposure for cluster and reduces the attack surface.
HighNoYes
Secure transfer protocol must be used for accessing storage account resources +
Use of secure transfer ensures server/service authentication and protects data in transit from network layer man-in-the-middle, eavesdropping, session-hijacking attacks. When enabling HTTPS one must remember to simultaneously disable access over plain HTTP else data can still be subject to compromise over clear text connections.
HighNoNo
Storage used for cluster must have encryption at rest enabled +
Using this feature ensures that sensitive data is stored encrypted at rest. This minimizes the risk of data loss from physical theft and also helps meet regulatory compliance requirements.
HighNoNo
Sensitive data must be stored on storage linked to cluster and not on cluster node disks +
Cluster node restart may cause loss of data present on cluster nodes. Also currently HDInsight does not support encryption at rest for cluster node disk.
HighNoNo
Access to cluster's storage must be restricted to virtual network of the cluster +
Restricting storage access within cluster network boundary reduces the attack surface.
MediumNoNo
All users/identities must be granted minimum required cluster operation permissions using Ambari Role Based Access Control (RBAC) +
Granting minimum access by leveraging RBAC feature ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
MediumNoNo
Only required users/identities must be granted access to Ambari views +
Granting access to only required users to Ambari views ensures minimum exposure of underline data resources.
MediumNoNo
Ambari admin password must be renewed after a regular interval +
Periodic key/password rotation is a good security hygiene practice as, over time, it minimizes the likelihood of data loss/compromise which can arise from key theft/brute forcing/recovery attacks.
MediumNoNo
Diagnostics must be enabled for cluster operations +
Diagnostics logs are needed for creating activity trail while investigating an incident or a compromise.
MediumNoNo
Secrets and keys must not be in plain text in notebooks and jobs +
Keeping secrets such as connection strings, passwords, keys, etc. in clear text can lead to easy compromise. Storing them in a secure place (like KeyVault) ensures that they are protected at rest.
MediumNoNo
+
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/KeyVault.md b/02-Secure-Development/ControlCoverage/Feature/KeyVault.md index 31896e91..d22975c3 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/KeyVault.md and b/02-Secure-Development/ControlCoverage/Feature/KeyVault.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/KubernetesService.md b/02-Secure-Development/ControlCoverage/Feature/KubernetesService.md new file mode 100644 index 00000000..6e9cc59e --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/KubernetesService.md @@ -0,0 +1,137 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + + + +

KubernetesService

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description & RationaleControlSeverityAutomated
Cluster RBAC must be enabled in Kubernetes Service
Enabling RBAC in a cluster lets you + finely control access to various operations at the cluster/node/pod/namespace scopes for different + stakeholders. Without RBAC enabled, every user has full access to the cluster which is a violation of + the principle of least privilege. Note that Azure Kubernetes Service does not currently support other + mechanisms to define authorization in Kubernetes (such as Attribute-based Access Control authorization + or Node authorization).
HighYes
AAD should be enabled in Kubernetes Service
Using the native enterprise directory for + authentication ensures that there is a built-in high level of assurance in the user identity + established for subsequent access control.All Enterprise subscriptions are automatically associated + with their enterprise directory (xxx.onmicrosoft.com) and users in the native directory are trusted for + authentication to enterprise subscriptions.
HighYes
All users/identities must be granted minimum required permissions using Role Based Access Control + (RBAC)
Granting minimum access by leveraging RBAC feature ensures that users are granted + just enough permissions to perform their tasks. This minimizes exposure of the resources in case of + user/service account compromise.
MediumYes
Do not directly or indirectly grant cluster admin level access to developers
Cluster admin + have full privileges to perform critical operations on Kubernetes cluster. Granting minimum required + access ensures that developer are granted just enough permissions to perform their tasks.
HighNo
The latest version of Kubernetes should be used
Running on older versions could mean you + are not using latest security classes. Usage of such old classes and types can make your application + vulnerable.
MediumYes
Make sure container images (including nested images) deployed in Kubernetes are from a trustworthy + source
If a Kubernetes Service runs an untrusted container image (or an untrusted nested + image), it can violate integrity of the infrastructure and lead to all types of security attacks.
HighNo
Do not use the default cluster namespace to deploy applications
Resources/Applications in + same namespace will have same access control (RBAC) policies. Users are granted permission on default + namespace if no other namespace is provided in rolebindings. As a result, the permissions in the + default namespace might not be appropriate if your application/workload is sensitive. It is hence + better to create a separate namespace.
MediumNo
All Kubernetes Service secrets should be stored in Key Vault
Keeping secrets such as DB + connection strings, passwords, keys, etc. in clear text can lead to easy compromise at various avenues + during an application's lifecycle. Storing them in a key vault ensures that they are protected at rest.
MediumNo
All the Kubernetes cluster nodes must have all the required OS patches installed
Unpatched + cluster nodes (VMs) are easy targets for compromise from various malware/trojan attacks that exploit + known vulnerabilities in operating systems and related software.
MediumNo
Pod Identity must be used for accessing other AAD-protected resources from the Kubernetes Service.
Pod + Identity allows your Kubernetes Service to easily access other AAD-protected resources such as Azure + Key Vault. The identity is managed by the Azure platform and eliminates the need to + provision/manage/rotate any secrets thus reducing the overall risk.
MediumNo
Issues/recommendations provided by kube advisor should be reviewed periodically
The + kube-advisor tool scans Kubernets cluster and reports on issues related to CPU and memory resource + consumption limits. If resource quotas are not applied then by default pod consumes all the CPU and + memory available, which impacts availability of another POD/application.
MediumNo
Monitoring must be enabled for Azure Kubernetes Service
Auditing enables log collection of + important system events pertinent to security. Regular monitoring of audit logs can help to detect any + suspicious and malicious activity early and respond in a timely manner.
MediumYes
Do not leave management ports open on Kubernetes nodes unless required
Open remote + management ports expose a VM/compute node to a high level of risk from internet-based attacks that + attempt to brute force credentials to gain admin access to the machine.
MediumYes
Data transit inside/across Kubernetes must use encrypted channel
Use of HTTPS ensures + server/service authentication and protects data in transit from network layer man-in-the-middle, + eavesdropping, session-hijacking attacks.
HighNo
Diagnostics logs must be enabled with a retention period of at least 365 days.
Logs should + be retained for a long enough period so that activity trail can be recreated when investigations are + required in the event of an incident or a compromise. A period of 1 year is typical for several + compliance requirements as well.
MediumYes
+ +
+ + diff --git a/02-Secure-Development/ControlCoverage/Feature/LoadBalancer.md b/02-Secure-Development/ControlCoverage/Feature/LoadBalancer.md index c305dcff..8ecb4e3e 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/LoadBalancer.md and b/02-Secure-Development/ControlCoverage/Feature/LoadBalancer.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/LogicApps.md b/02-Secure-Development/ControlCoverage/Feature/LogicApps.md index b2d7bde8..9d4a0984 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/LogicApps.md and b/02-Secure-Development/ControlCoverage/Feature/LogicApps.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/NotificationHub.md b/02-Secure-Development/ControlCoverage/Feature/NotificationHub.md index 8de1834f..1c6400dc 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/NotificationHub.md and b/02-Secure-Development/ControlCoverage/Feature/NotificationHub.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/ODG.md b/02-Secure-Development/ControlCoverage/Feature/ODG.md index 832b966f..2bac40e5 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/ODG.md and b/02-Secure-Development/ControlCoverage/Feature/ODG.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/RedisCache.md b/02-Secure-Development/ControlCoverage/Feature/RedisCache.md index 3ad86a33..d438d9bf 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/RedisCache.md and b/02-Secure-Development/ControlCoverage/Feature/RedisCache.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/SQLDatabase.md b/02-Secure-Development/ControlCoverage/Feature/SQLDatabase.md index 4333ae78..0e48eb01 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/SQLDatabase.md and b/02-Secure-Development/ControlCoverage/Feature/SQLDatabase.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/Scripts/ADAppProxyScanScript.ps1.txt b/02-Secure-Development/ControlCoverage/Feature/Scripts/ADAppProxyScanScript.ps1.txt new file mode 100644 index 00000000..746ae66b --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/Scripts/ADAppProxyScanScript.ps1.txt @@ -0,0 +1,67 @@ +######--------------------------Prerequisite----------------------------------###### +# 1. You should be AAD Application Administrator (or higher privilege) in Azure Active Directory. +# Refer: https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#application-administrator +# 2. Provide user input as mentioned in script + +######------------------------------------------------------------------------###### + +#Install and import AD module +$moduleName = "AzureAD" +$module = Get-Module -Name $moduleName -ListAvailable +if($null -eq $module) +{ + Install-Module -Name $moduleName +} +Import-Module $moduleName + +#Login +Connect-AzureAD + +#User input - Provide ObjectID of AAD application configured for Application Proxy in Azure Active Directory +$AADAppObjID = $null +while([string]::IsNullOrWhiteSpace($AADAppObjID) -and $AADAppObjID -ne 'N') +{ + $AADAppObjID = Read-Host "Provide ObjectID of AAD application configured for Application Proxy in Azure Active Directory. Enter 'N' to exit.`n" +} +if($AADAppObjID -eq 'N') +{ + return; +} +else +{ + $AADAppObjID = $AADAppObjID.Trim() +} + +#ControlID: Azure_ApplicationProxy_AuthN_Use_AAD_PreAuth +write-host "Checking: [Application Proxy]-[AAD Authentication must be enabled as a pre-authentication method on your app]" -ForegroundColor Cyan +$appProxy = Get-AzureADApplicationProxyApplication -ObjectId $aadAppObjID +if($appProxy) +{ + $preAuthType = $appProxy.ExternalAuthenticationType + if($preAuthType -eq 'AadPreAuthentication') + { + write-host "**Passed**" -ForegroundColor Green + } + else + { + write-host "**Failed**" -ForegroundColor Red + } + + #ControlID: Azure_ApplicationProxy_Config_Enable_HTTPOnly_Cookie + write-host "Checking: [Application Proxy]-[HTTP-Only cookie must be enabled while configuring App Proxy wherever possible]" -ForegroundColor Cyan + if($appProxy.IsHttpOnlyCookieEnabled -eq $true) + { + write-host "**Passed**" -ForegroundColor Green + } + else + { + write-host "**Failed**" -ForegroundColor Red + } +} +else +{ + write-host "Something went wrong. Check prerequisites and try again." +} + + + diff --git a/02-Secure-Development/ControlCoverage/Feature/Search.md b/02-Secure-Development/ControlCoverage/Feature/Search.md index b6b65d51..0f4e4b38 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/Search.md and b/02-Secure-Development/ControlCoverage/Feature/Search.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/ServiceBus.md b/02-Secure-Development/ControlCoverage/Feature/ServiceBus.md index af41648b..37e92bfe 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/ServiceBus.md and b/02-Secure-Development/ControlCoverage/Feature/ServiceBus.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/ServiceFabric.md b/02-Secure-Development/ControlCoverage/Feature/ServiceFabric.md index 833563c4..d475ceb2 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/ServiceFabric.md and b/02-Secure-Development/ControlCoverage/Feature/ServiceFabric.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/Storage.md b/02-Secure-Development/ControlCoverage/Feature/Storage.md index 570f703f..cc5aa654 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/Storage.md and b/02-Secure-Development/ControlCoverage/Feature/Storage.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/StreamAnalytics.md b/02-Secure-Development/ControlCoverage/Feature/StreamAnalytics.md index c3b278b2..93fa8015 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/StreamAnalytics.md and b/02-Secure-Development/ControlCoverage/Feature/StreamAnalytics.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/SubscriptionCore.md b/02-Secure-Development/ControlCoverage/Feature/SubscriptionCore.md index 217a9122..5fae8309 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/SubscriptionCore.md and b/02-Secure-Development/ControlCoverage/Feature/SubscriptionCore.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/TrafficManager.md b/02-Secure-Development/ControlCoverage/Feature/TrafficManager.md index 0ea69058..d38722db 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/TrafficManager.md and b/02-Secure-Development/ControlCoverage/Feature/TrafficManager.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/VirtualMachine.md b/02-Secure-Development/ControlCoverage/Feature/VirtualMachine.md index e433b8c7..38e5fea7 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/VirtualMachine.md and b/02-Secure-Development/ControlCoverage/Feature/VirtualMachine.md differ diff --git a/02-Secure-Development/ControlCoverage/Feature/VirtualMachineScaleSet.md b/02-Secure-Development/ControlCoverage/Feature/VirtualMachineScaleSet.md new file mode 100644 index 00000000..a892bdce --- /dev/null +++ b/02-Secure-Development/ControlCoverage/Feature/VirtualMachineScaleSet.md @@ -0,0 +1,41 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + + + + + +

Virtual Machine Scale Set

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description & RationaleControlSeverityAutomatedFix Script
Log analytics agent should be installed on Virtual Machine Scale Set
Installing the Log Analytics extension for Windows and Linux allows Azure Monitor to collect data from your Azure VM Scale Sets which can be used for detailed analysis and correlation of events.
MediumYesNo
Antimalware must be enabled with real time protection on Virtual Machine Scale Set
Enabling antimalware protection minimizes the risks from existing and new attacks from various types of malware. Microsoft Antimalware provide real-time protection, scheduled scanning, malware remediation, signature updates, engine updates, samples reporting, exclusion event collection etc.
HighYesNo
Diagnostics (IaaSDiagnostics extension on Windows; LinuxDiagnostic extension on Linux) must be enabled on Virtual Machine Scale Set
Diagnostics logs are needed for creating activity trail while investigating an incident or a compromise.
MediumYesNo
Disk encryption must be enabled on both OS and data disks for Windows Virtual Machine Scale Set
Using this feature ensures that sensitive data is stored encrypted at rest. This minimizes the risk of data loss from physical theft and also helps meet regulatory compliance requirements. In the case of VM Scale Set, both OS and data disks may contain sensitive information that needs to be protected at rest. Hence disk encryption must be enabled for both.
HighYesNo
All VMs in VM Scale Set must be up-to-date with the latest scale set model
All the security configurations applied on VM Scale Set will be effective only if all the individual VM instances in Scale Set is up-to-date with the latest overall Scale Set model.
HighYesNo
All users/identities must be granted minimum required permissions using Role Based Access Control (RBAC)
Granting minimum access by leveraging RBAC feature ensures that users are granted just enough permissions to perform their tasks. This minimizes exposure of the resources in case of user/service account compromise.
MediumYesNo
Public IPs on a Virtual Machine Scale Set instances should be carefully reviewed
Public IPs provide direct access over the internet exposing the VMSS instance to attacks over the public network. Hence each public IP on a VMSS instance must be reviewed carefully.
HighYesNo
NSG must be configured for Virtual Machine Scale Set
Restricting inbound and outbound traffic via NSGs limits the network exposure of a VM Scale Set by reducing the attack surface.
MediumYesNo
Do not leave management ports open on Virtual Machine Scale Set
Open remote management ports expose a VMSS instance/compute node to a high level of risk from internet-based attacks that attempt to brute force credentials to gain admin access to the machine.
HighYesNo
+ diff --git a/02-Secure-Development/ControlCoverage/Feature/VirtualNetwork.md b/02-Secure-Development/ControlCoverage/Feature/VirtualNetwork.md index 0d01f2a3..d1af7711 100644 Binary files a/02-Secure-Development/ControlCoverage/Feature/VirtualNetwork.md and b/02-Secure-Development/ControlCoverage/Feature/VirtualNetwork.md differ diff --git a/02-Secure-Development/ControlCoverage/README.md b/02-Secure-Development/ControlCoverage/README.md index 4c93fd01..803e3106 100644 --- a/02-Secure-Development/ControlCoverage/README.md +++ b/02-Secure-Development/ControlCoverage/README.md @@ -1,26 +1,42 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + ## Security controls covered by the Secure DevOps Kit for Azure This page displays security controls that are automated via the devops kit and also controls that have to manually verified. Controls have a 'Severity' field to help distinguish issues by degree of risk. Apart from that the automated flag indicates whether a particular control is automated and 'Fix Script' provides the availability of a 'control fix' script that the user can review and run to apply the fixes. ### Azure Services supported by AzSK +Below resource types can be checked for validating the security controls in SVT(GRS, GSS and CICD SVT task). please refer [this](../03-Security-In-CICD/Readme.md#arm-template-checker---control-coverage) for supported resource types in ARMChecker) + |FeatureName|Resource Type| |---|---| |[Subscription](Feature/SubscriptionCore.md)|| |[Alerts List](Feature/AlertList.md)|| |[ARMPolicy List](Feature/ARMPolicyList.md)|| -|[AnalysisServices](Feature/AnalysisServices.md)|Microsoft.AnalysisServices/servers| +|[AzSKCfg](Feature/AzSKCfg.md)|| +|[APIConnection](Feature/APIConnection.md)|Microsoft.Web/connections| +|[APIManagement](Feature/APIManagement.md)|Microsoft.ApiManagement/service| |[AppService](Feature/AppService.md)|Microsoft.Web/sites| +|[ApplicationProxy](Feature/ApplicationProxy.md)|NA| |[Automation](Feature/Automation.md)|Microsoft.Automation/automationAccounts| |[Batch](Feature/Batch.md)|Microsoft.Batch/batchAccounts| +|[BotService](Feature/BotService.md)|Microsoft.BotService/botServices| |[CDN](Feature/CDN.md)|Microsoft.Cdn/profiles| |[CloudService](Feature/CloudService.md)|Microsoft.ClassicCompute/domainNames| +|[ContainerInstances](Feature/ContainerInstances.md)|Microsoft.ContainerInstance/containerGroups| +|[ContainerRegistry](Feature/ContainerRegistry.md)|Microsoft.ContainerRegistry/registries| |[CosmosDB](Feature/CosmosDB.md)|Microsoft.DocumentDb/databaseAccounts| +|[DataBricks](Feature/Databricks.md)|Microsoft.Databricks/workspaces| |[DataFactory](Feature/DataFactory.md)|Microsoft.DataFactory/dataFactories| +|[DataFactoryV2](Feature/DataFactoryV2.md)|Microsoft.DataFactory/factories| |[DataLakeAnalytics](Feature/DataLakeAnalytics.md)|Microsoft.DataLakeAnalytics/accounts| |[DataLakeStore](Feature/DataLakeStore.md)|Microsoft.DataLakeStore/accounts| +|[DBforPostgreSQL](Feature/DBforPostgreSQL.md)|Microsoft.DBforPostgreSQL/servers| |[ERvNet](Feature/ERvNet.md)|Microsoft.Network/virtualNetworks| |[EventHub](Feature/EventHub.md)|Microsoft.Eventhub/namespaces| +|[HDInsight](Feature/HDInsight.md)|Microsoft.HDInsight/clusters| |[KeyVault](Feature/KeyVault.md)|Microsoft.KeyVault/vaults| +|[KubernetesService](Feature/KubernetesService.md)|Microsoft.ContainerService/ManagedClusters| |[LoadBalancer](Feature/LoadBalancer.md)|Microsoft.Network/loadBalancers| |[LogicApps](Feature/LogicApps.md)|Microsoft.Logic/Workflows| |[NotificationHub](Feature/NotificationHub.md)|Microsoft.NotificationHubs/namespaces/notificationHubs| @@ -35,5 +51,6 @@ This page displays security controls that are automated via the devops kit and a |[TrafficManager](Feature/TrafficManager.md)|Microsoft.Network/trafficmanagerprofiles| |[VirtualMachine](Feature/VirtualMachine.md)|Microsoft.Compute/virtualMachines| |[VirtualNetwork](Feature/VirtualNetwork.md)|Microsoft.Network/virtualNetworks| +|[DBForMySql](Feature/DBForMySql.md)|Microsoft.MySql/servers| diff --git a/02-Secure-Development/Readme.md b/02-Secure-Development/Readme.md index db2fcb09..5f39dbaa 100644 --- a/02-Secure-Development/Readme.md +++ b/02-Secure-Development/Readme.md @@ -1,3 +1,8 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # Secure Development ![Secure_Development](../Images/Secure_Development.png) @@ -12,6 +17,12 @@ - [Execute SVTs for a specific resource type](Readme.md#execute-svts-for-a-specific-resource-type) - [Execute SVTs in Baseline mode](Readme.md#execute-svts-in-baseline-mode) - [Execute SVTs using "-UsePartialCommits" switch](Readme.md#execute-svts-using--usepartialcommits-switch) +- [Execute SVT excluding some resource groups](Readme.md#execute-svts-excluding-some-resource-groups) +- [Execute SVT excluding some resources](Readme.md#execute-svts-excluding-some-resources) +- [Execute SVT excluding a resource type](Readme.md#execute-svts-excluding-a-resource-type) +- [Execute SVT excluding some controls from scan](Readme.md#execute-svts-excluding-some-controls-from-scan) +- [Generate FixScripts for controls that support AutoFix while executing SVTs](Readme.md#generate-fixscripts-for-controls-that-support-autofix-while-executing-svts) +- [Prevent the output folder from opening automatically at the end of SVTs](Readme.md#prevent-the-output-folder-from-opening-automatically-at-the-end-of-svts) - [Understand the scan reports](Readme.md#understand-the-scan-reports) - [Generate output report in PDF format](Readme.md#generate-output-report-in-pdf-format) - [FAQs](Readme.md#faqs) @@ -40,14 +51,14 @@ ## Security Verification Tests (SVT) > **Prerequisites:** > For all commands in this feature it is assumed that you have: -> 1. Logged in to your Azure account using Login-AzureRmAccount from a PowerShell ISE. -> 2. Selected a subscription using Set-AzureRmContext. +> 1. Logged in to your Azure account using Connect-AzAccount from a PowerShell ISE. +> 2. Selected a subscription using Set-AzContext. ### Overview Security Verifications Tests (or SVTs) represent the core of security testing functionality of the AzSK. For all the prominent features in Azure (e.g., Web Apps, Storage, SQL DB, Key Vault, etc.), -the AzSK ccan perform automated security checks against Azure resources of those types. +the AzSK can perform automated security checks against Azure resources of those types. These checks are based on security standards and best practices as applicable for sensitive corporate data at Microsoft. In general, these are likely to be applicable for most scenarios that involve processing sensitive data in other environments. @@ -163,16 +174,34 @@ The parameters required are: [Back to top…](Readme.md#contents) +### Execute SVTs for specific control severity + + +```PowerShell + Get-AzSKAzureServicesSecurityStatus -SubscriptionId -Severity "High, Medium" +``` + +The above command execution will result in scanning of 'High' and 'Medium' controls for Azure resources in your subscription + +> **Note**: If you have mapped the AzSK control severity in your custom org policy settings +> (refer: [Control severity mapping for your org](https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org#testing-3) to know about mapping), then the final severities mapped should be passed as parameter values to -Severity parameter. + +[Back to top…](Readme.md#contents) ### Execute SVTs in Baseline mode In 'baseline mode' a centrally defined 'control baseline' is used as the target control set for scanning. The cmdlet below scans azure resources in a subscription in Baseline mode and generates a status report: ```PowerShell Get-AzSKAzureServicesSecurityStatus -SubscriptionId -UseBaselineControls + +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -UsePreviewBaselineControls + +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -UseBaselineControls -UsePreviewBaselineControls ``` The parameters required are: - SubscriptionId – Subscription ID is the identifier of your Azure subscription. - UseBaselineControls – UseBaselineControls is the flag used to enable scanning of resources in Baseline mode. +- UsePreviewBaselineControls – UsePreviewBaselineControls is the flag used to enable scanning of resources in Preview Baseline mode. [Back to top…](Readme.md#contents) @@ -182,7 +211,60 @@ The Get-AzSKAzureServicesSecurityStatus command now supports checkpointing via a ```PowerShell Get-AzSKAzureServicesSecurityStatus -SubscriptionId -UsePartialCommits ``` - +[Back to top…](Readme.md#contents) + +### Execute SVTs excluding some resource groups +The Get-AzSKAzureServicesSecurityStatus command now supports a switch 'ExcludeResourceGroupNames' to exclude some of the resource groups from getting scanned. The cmdlet below will not scan the resource groups 'azsktestRg' and 'azsktestRg1'. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeResourceGroupNames "azsktestRg,azsktestRg2" +``` +[Back to top…](Readme.md#contents) + +### Execute SVTs excluding some resources +The Get-AzSKAzureServicesSecurityStatus command now supports a switch 'ExcludeResourceNames' to exclude some of the resources from getting scanned. The cmdlet below will not scan the resource groups 'azsktestApp' and 'azsktestApp2'. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeResourceNames "azsktestApp,azsktestApp2" +``` +[Back to top…](Readme.md#contents) + +### Execute SVTs excluding a resource type +The Get-AzSKAzureServicesSecurityStatus command now supports a switch 'ExcludeResourceTypeName' to exclude resources of a particular type supported by AzSK from getting scanned. The cmdlet below will not scan any Databricks resources. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeResourceTypeName Databricks +``` +> **Note:** Currently there is provision to exclude only one type of resources using switch '-ExcludeResourceTypeName'. To exclude multiple types of resources from getting scanned the switch'-ExcludeTags' can be used passing the user friendly name for the resource type as specified [here](Readme.md#execute-svts-for-a-specific-resource-type). The cmdlet below will exclude all resources belonging to the type 'AppServices' or 'Databricks' from getting scanned. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeResourceTypeName Databricks -ExcludeTags 'AppService' +``` +[Back to top…](Readme.md#contents) + +### Execute SVTs excluding some controls from scan +The Get-AzSKAzureServicesSecurityStatus command now supports a switch 'ExcludeControlIds' to exclude AzSK security controls from getting scanned. +The cmdlet below will not scan 'Azure_Storage_DP_Rotate_Keys' control for any Storage type resource. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeControlIds 'Azure_Storage_DP_Rotate_Keys' +``` +The cmdlet below will not scan 'Azure_Storage_DP_Rotate_Keys' and 'Azure_Storage_AuthZ_Allow_Limited_Access_to_Services' control for any Storage type resource. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ExcludeControlIds "Azure_Storage_DP_Rotate_Keys, Azure_Storage_AuthZ_Allow_Limited_Access_to_Services" +``` +[Back to top…](Readme.md#contents) + +### Generate FixScripts for controls that support AutoFix while executing SVTs +The command below will not only scan the controls for all the resources in the subscription but also produce scripts to fix the controls that support AutoFix. To know if a control supports AutoFix or not, look at the value for the corresponding control under the column *SupportsAutoFix* in the SecurityReport. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -GenerateFixScript" +``` +Note that this switch can be used with any variant of the Get-AzSKAzureServicesSecurityStatus command. You can read more about FixScripts [here](https://github.com/azsk/DevOpsKit-docs/tree/master/00c-Addressing-Control-Failures#automatically-generating-fixes-1). + +[Back to top…](Readme.md#contents) + +### Prevent the output folder from opening automatically at the end of SVTs +When you run an AzSK scan, the output folder containing all the necessary components opens up automatically for you at the end of the scan. If you wish to prevent this, you just need to add the flag *-DoNotOpenOutputFolder* to any variant of the Get-AzSKAzureServicesSecurityStatus command, as shown in the example below. +```PowerShell +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -DoNotOpenOutputFolder" +``` + [Back to top…](Readme.md#contents) ### Understand the scan reports @@ -218,7 +300,7 @@ The contents of the output folder are organized as under: You can use these outputs as follows - 1. The SecurityReport.CSV file provides a quick glimpse of the control results. Investigate those that say 'Verify' or 'Failed'. -2. For 'Failed' or 'Verify' controls, look in the .LOG file (search for 'failed' or by control-id). Understand what caused the control the fail. +2. For 'Failed' or 'Verify' controls, look in the .LOG file (search for 'failed' or by control-id). Understand what caused the control to fail. 3. For 'Verify' controls, you will also find the SecurityEvaluationData.JSON file handy. 4. For some controls, you can also use the 'Recommendation' field in the control output to get the PS command you may need to use. 5. Make any changes to the subscription/resource configurations based on steps 2, 3 and 4. @@ -252,17 +334,20 @@ The PDF report consists of following sections: ### FAQs #### What Azure resource types that can be checked? -Below resource types can be checked for validating the security controls +Below resource types can be checked for validating the security controls in SVT(GRS, GSS and CICD SVT task). please refer [this](../03-Security-In-CICD/Readme.md#arm-template-checker---control-coverage) for supported resource types in ARMChecker) | Resource Name |Resource Type Name |Resource Type| |-------| ------------- | ----------- | |Analysis Services |AnalysisService |Microsoft.AnalysisServices/servers| |API Connection|APIConnection|Microsoft.Web/connections| +|API Management|APIManagement|Microsoft.ApiManagement/service| |App Services|AppService |Microsoft.Web/sites| -|Automation Acocunt|Automation|Microsoft.Automation/automationAccounts| +|Automation Account|Automation|Microsoft.Automation/automationAccounts| |Batch accounts |Batch |Microsoft.Batch/batchAccounts| |CDN profiles |CDN |Microsoft.Cdn/profiles| |Cloud Services|CloudService |Microsoft.ClassicCompute/domainNames| +|Container Instances |ContainerInstances |Microsoft.ContainerInstance/containerGroups | +|Container Registry |ContainerRegistry |Microsoft.ContainerRegistry/registries | |Cosmos DB|Cosmos DB|Microsoft.DocumentDb/databaseAccounts| |Data Factories |DataFactory |Microsoft.DataFactory/dataFactories| |Data Lake Analytics|DataLakeAnalytics |Microsoft.DataLakeAnalytics/accounts| @@ -270,6 +355,7 @@ Below resource types can be checked for validating the security controls |Express Route-connected Virtual Networks|ERvNet |Microsoft.Network/virtualNetworks| |Event Hubs|EventHub |Microsoft.Eventhub/namespaces| |Key Vaults|KeyVault |Microsoft.KeyVault/vaults| +|Kubernetes Service |KubernetesService |Microsoft.ContainerService/ManagedClusters | |Load Balancer|LoadBalancer|Microsoft.Network/loadBalancers| |Logic Apps|LogicApps |Microsoft.Logic/Workflows| |Notification Hubs|NotificationHub |Microsoft.NotificationHubs/namespaces/notificationHubs| @@ -289,7 +375,7 @@ This list continues to grow so best way to confirm is to look at the output of t ```PowerShell Get-AzSKSupportedResourceTypes ``` -> We regularly add SVT coverage for more Azure features. Please write to us (mailto:AzSDKSupExt@microsoft.com) if you are looking for SVTs for a service not listed here. +> We regularly add SVT coverage for more Azure features. Please write to us (mailto:azsksup@microsoft.com) if you are looking for SVTs for a service not listed here. #### What do the different columns in the status report mean? Status report will be in CSV format and will contain below columns @@ -311,11 +397,31 @@ Note that not all security checks are automatable. The 'non-automated' checks (t - Reference - Link to detailed document/explanation. - Recommendation - Recommended steps to implement a fix for a failed control. +#### What are Owner access controls? Why can't those be run via CA and need to be run manually?

(Or)

I have setup AzSK Continuous Assurance on my subscription. Do I still need to run the scans locally?

Description:
Running the scan locally for all the resources in the subscription is time consuming. Do I still need to run that even though I have already setup Continuous Assurance on my subscription? + +Continuous Assurance scans and locally run scans have different permission models. Some of the AzSK controls need elevated permissions (e.g. Owner permissions, GraphRead access etc.). CA being runnning using SPN context, can't scan controls which need such elevated permissions. Note that SPN should not be granted elevated permissions from security stand point. + +That's the reason you or anyone on your team who has elevated permissions (as mentioned in the control recommendations) on the subscription; need to run the manual scans periodically. + +You can certainly minimize the time taken for the scan by runnning only those controls which are not run by CA. + +``` +# Command to scan subscription level controls +Get-AzSKSubscriptionSecurityStatus -SubscriptionId '' -FilterTags "OwnerAccess,GraphRead" + +# Command to scan resource level controls +Get-AzSKAzureServicesSecurityStatus -SubscriptionId '' -FilterTags "OwnerAccess,GraphRead" + +# Command to scan both subscription and resource level controls +Get-AzSKControlsStatus -SubscriptionId '' -FilterTags "OwnerAccess,GraphRead" + +``` + #### How can I find out what to do for controls that are marked as 'manual'? -Refer the recommendations provided in the output CSV file for the security controls defined by AzSK. You can also email to AzSDKSupExt@microsoft.com or reach out to your security point of contact for any queries. +Refer the recommendations provided in the output CSV file for the security controls defined by AzSK. You can also email to AzSKSup@microsoft.com or reach out to your security point of contact for any queries. #### How can I implement fixes for the failed ones which have no auto-fix available? -Refer the recommendations provided in the output CSV file for the security controls defined by AzSK. You can also email to AzSDKSupExt@microsoft.com or reach out to your security point of contact for any queries. +Refer the recommendations provided in the output CSV file for the security controls defined by AzSK. You can also email to AzSKSup@microsoft.com or reach out to your security point of contact for any queries. #### Troubleshooting |Error |Comments| @@ -361,7 +467,7 @@ Additionally the following other 'protective' checks are also done: # Security IntelliSense (Dev-SecIntel) -------------------------------------------------------------- -> Note: Security IntelliSense extension works on Visual Studio 2015 Update 3 or later and Visual Studio 2017 +> Note: Security IntelliSense extension works on Visual Studio 2015 Update 3 or later, Visual Studio 2017 and Visual Studio 2019. @@ -382,24 +488,34 @@ The screenshots below show the core functionality at work: - Error and warning indications for incorrect and possibly vulnerable code: (E.g., use of custom token cache in ADAL scenario) -![SecIntel_Ex_1](../Images/02_SecIntel_Ex_1.png) +![SecIntel_Ex_1](../Images/02_SecIntel_Ex_1.PNG) - Suggestions for corrections/compliant coding practices: (E.g., Instead of Random, the RNGCryptoServiceProvider class should be used in a crypto context.) -![02_SecIntel_Ex_2](../Images/02_SecIntel_Ex_2.png) +![02_SecIntel_Ex_2](../Images/02_SecIntel_Ex_2.PNG) [Back to top…](Readme.md#contents) ### How do I enable Security IntelliSense on my dev box? -- Open Visual Studio 2015 -- Go to **Tools** -> **Extensions and Updates** -> In the left sidebar select **Online** -> **Visual Studio Gallery** and search for **Security IntelliSense** in the right sidebar +* For Visual Studio 2015/2017 + - Open Visual Studio + + - Go to **Tools** -> **Extensions and Updates** -> In the left sidebar select **Online** -> **Visual Studio Gallery** and search for **Security IntelliSense** in the right sidebar + +* For Visual Studio 2019 + - Open Visual Studio. + + (Note: If you are using a Preview release of VS2019 then you would need to start Visual Studio in admin mode.) + + - Go to **Extensions** -> **Manage Extensions** -> In the left sidebar select **Online** -> **Visual Studio Marketplace** and search for **Security IntelliSense** in the right sidebar -![02_SecIntel_VSGallery_Download](../Images/02_SecIntel_VSGallery_Download.png) +![02_SecIntel_VSGallery_Download](../Images/02_SecIntel_VSGallery_Download.PNG) -- Select Security IntelliSense item and click **Download** -- After download completes, in the pop-up click **Install** -- After installation completes, **restart Visual Studio** +- Select Security IntelliSense item and click **Download** or **Install** +- After download completes, close the Visual Studio +- It will open **VSIX Installer**, click on **Modify**. +- After installation completes, **Start Visual Studio** [Back to top…](Readme.md#contents) ### Is there a sample I can use to see how it works? @@ -417,7 +533,7 @@ extension installation per steps from above). - Go to View->Solution Explorer and then open one of demo files (e.g., "CryptoSample.cs") in the VS editor. - You should see SecIntel in action -- i.e., code that is in violation of the rules in use for the SecIntel VSIX plugin will appear as red-squigglies (errors) and green-squigglies (warnings). - ![02_SecIntel_Suggestion](../Images/02_SecIntel_Suggestion.png) + ![02_SecIntel_Suggestion](../Images/02_SecIntel_Suggestion.PNG) - Note: In the currently implemented behavior of the extension, 'errors' don’t actually fail the build. We will change this behavior in an upcoming sprint. After that anything that is considered an 'error' will start failing @@ -483,7 +599,7 @@ the supported rule templates. - If you have the extension installed, you will see a screen such as below with options to "Disable" or "Uninstall" the extension. - Click "Uninstall" and restart Visual Studio. -![02_SecIntel_VSGallery](../Images/02_SecIntel_VSGallery.png) +![02_SecIntel_VSGallery](../Images/02_SecIntel_VSGallery_Uninstall.PNG) [Back to top…](Readme.md#contents) ### What default compiler actions are configured? diff --git a/02-Secure-Development/Security_IntelliSense_rules_list.md b/02-Secure-Development/Security_IntelliSense_rules_list.md index e2f8b4f9..e7487bc9 100644 --- a/02-Secure-Development/Security_IntelliSense_rules_list.md +++ b/02-Secure-Development/Security_IntelliSense_rules_list.md @@ -1,4 +1,7 @@ -## **Security IntelliSense Rule List** +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +## **Security IntelliSense Rule List** ### **Rule - appsec_xml_doc_dtdprocessing_parse** @@ -408,7 +411,7 @@ The RijndaelManaged class supports algorithm modes which are not FIPS approved. **Message**
-The MD5 hash algorigthm is weak and must not be used. +The MD5 hash algorithm is weak and must not be used.

**Description** @@ -421,7 +424,7 @@ The MD5 hash algorithm has been broken and many practical attacks have been foun **Message**
-The SHA1 hash algorigthm is weak and must not be used. +The SHA1 hash algorithm is weak and must not be used.

**Description** diff --git a/03-Security-In-CICD/Readme.md b/03-Security-In-CICD/Readme.md index ed6b4822..7a3800e7 100644 --- a/03-Security-In-CICD/Readme.md +++ b/03-Security-In-CICD/Readme.md @@ -1,11 +1,22 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + +>NOTE: +>The OMS* parameter/variable names will soon be deprecated. Please ensure that you have made the necessary changes to CA, CICD and AzSK Monitoring Solution as per below: +> 1. Updated CA setups with new names ([details here](../04-Continous-Assurance#updating-an-existing-continuous-assurance-setup)). (Not required for CSEO subscriptions!) +> 2. Switched to new names in CICD extension ([details here](../03-Security-In-CICD#advanced-cicd-scanning-capabilities)). (Required for all subscriptions) +> 3. Start using the new parameters for [CA](../04-Continous-Assurance#setting-up-continuous-assurance---step-by-step) and [AzSK Monitoring Solution](../05-Alerting-and-Monitoring#1-c). # Security Verification Tests (SVTs) -![Security_In_CICD](../Images/Security_In_CICD.jpg) +![Security_In_CICD](../Images/Security_In_CICD.png) ## Contents - [Overview](Readme.md#overview) -## [Security Verification Tests (SVTs) in VSTS pipeline](Readme.md#security-verification-tests-svts-in-VSTS-pipeline) +## [Security Verification Tests (SVTs) in VSTS pipeline](Readme.md#security-verification-tests-svts-in-VSTS-pipeline) - [Enable AzSK extension for your VSTS](Readme.md#enable-azsk-extension-for-your-vsts) - [Walkthrough](Readme.md#walkthrough) - [Adding SVTs in the release pipeline](Readme.md#adding-svts-in-the-release-pipeline) @@ -19,6 +30,24 @@ - [Adding SVTs in the Jenkins pipeline](Readme.md#adding-svts-in-the-jenkins-pipeline) - [Verifying that SVTs have been added and configured correctly](Readme.md#verifying-that-the-svts-have-been-added-and-configured-correctly-1) - [Remediating Failures and Next Steps](Readme.md#remediating-failures-and-next-steps) + +## [AzSK ARM Template Checker](Readme.md#azsk-arm-template-checker) +- [Overview](Readme.md#overview-1) + - [Execute ARM Template Checker in Baseline mode](Readme.md#execute-arm-template-checker-in-baseline-mode) + - [Execute ARM Template Checker for specific controls](Readme.md#execute-arm-template-checker-for-specific-controls) + - [Execute ARM Template Checker excluding some controls from scan](Readme.md#execute-arm-template-excluding-some-controls-from-scan) + - [ARM Template Checker - Control coverage](Readme.md#arm-template-checker---control-coverage) +- [Enable AzSK extension for your VSTS](Readme.md#enable-azsk-extension-for-your-vsts-1) +- [Walkthrough](Readme.md#walkthrough-2) + - [Adding ARM Template Checker in VSTS pipeline](Readme.md#adding-arm-template-checker-in-vsts-pipeline) + - [Verifying that ARM Template Checker have been added and configured correctly](Readme.md#verifying-that-the-arm-template-checker-have-been-added-and-configured-correctly) + - [Exclude files from scan](Readme.md#exclude-files-from-scan) + - [Skip certain controls during scan](Readme.md#skip-certain-controls-during-scan) + - [Use external parameter file](Readme.md#use-external-parameter-file) + - [Advanced CICD scanning capabilities](Readme.md#advanced-cicd-scanning-capabilities-1) + - [Extending ARM Template Checker for your organization](Readme.md#extending-arm-template-checker-for-your-organization) + + ------------------------------------------------------------------ ### Overview The AzSK contains Security Verification Tests (SVTs) for multiple PaaS and IaaS services of the Azure platform. @@ -42,7 +71,7 @@ despite failures while sending an email to the build/release owners or to hold p manually approves, etc. Furthermore, if all SVTs pass in the pre-prod environment, then a release can be 'promoted' to prod.) -Outcomes of the SVT execution can also be routed to an OMS workspace configured to receive various events +Outcomes of the SVT execution can also be routed to a Log Analytics workspace configured to receive various events generated by the AzSK. [Back to top...](Readme.md#contents) @@ -51,10 +80,11 @@ generated by the AzSK. ### Enable AzSK extension for your VSTS -This extesion has been published to the VSTS gallery under "Build and Release" category. +This extension has been published to the VSTS gallery under "Build and Release" category. You can now install this extension from the Marketplace directly (https://marketplace.visualstudio.com/items?itemName=azsdktm.AzSDK-task). > **Note:** You can also install this extension on your on-prem TFS instance. Please follow the instructions detailed at: -> https://docs.microsoft.com/en-us/vsts/marketplace/get-tfs-extensions +> https://docs.microsoft.com/en-us/vsts/marketplace/get-tfs-extensions
+> **Note:** AzSK_SVT task is available in 'Release' pipeline tasks only. ### Walkthrough This part assumes that you are familiar with VS build tasks and pipelines at a basic level. To demonstrate @@ -67,7 +97,7 @@ Azure subscription and resources is seamlessly integrated into CICD. **Step-1:** Create a release definition or open an existing one. -(Note: Here we will edit "AzSKDemoApp_SVTs_Rel3" which is part of our test instance of VSTS. +(Note: Here we will edit "AzSK_SVT" which is part of our test instance of VSTS. We also have a default build definition upstream to this which is not shown here as that is a pretty standard web app build flow using an MSBuild task.) @@ -77,7 +107,7 @@ pipeline that builds and deploys a web app (or App Service) from VSTS to an Azur Let us take a look at the steps needed to add the AzSK-SVT task to the release definition. -![03_Create_Release_Defination](../Images/03_Create_Release_Defination.png) +![03_Create_Release_Definition](../Images/03_Create_Release_Definition.png) **Step-2:** Add the AzSK-SVT release task to the pipeline. Click on "Add Tasks", and select "AzSK Security Verification Test". @@ -88,7 +118,7 @@ Click on "Add" and "Close". > **Note:** The VSTS dialog doesn't provide a good visual indication but the task does get added when you click "Add" once! -![03_Task_Catalog](../Images/03_Task_Catalog.png) +![03_Task_Catalog](../Images/03_Task_Catalog.PNG) **Step-3:** Specify the input parameters for the SVT task. The "AzSK_SVTs" task starts showing in the "Run on Agent" list and displays some configuration inputs @@ -97,67 +127,68 @@ while running the AzSK SVTs manually - you can choose to specify the target reso a {tagname, tagvalue} pair based on how your application's resources are organized. When the pipeline executes, SVTs will scan the specified set of resources. -Along with input parameter, you can check for below options -
**Enable OMS Logging:** Switch to enable this task to publish SVT evalution results to an OMS workspace. Steps to configure OMS credential are explained in Step-4 -
**Aggregate Control Status:** Switch to aggregate the SVTs control output. When this is turned off it would show all the failed individual controls in the task summary output. -
**Do not auto-update AzSK:** Switch to toggle auto update of AzSK and required AzureRM modules on the build server. Keep this un-checked for Hosted agent and Hosted VS2017 and while using SVT task fot the first time and if you want to update AZSK the version of AzSK. -![03_IP_Parameter_for_Task](../Images/03_IP_Parameter_for_Task.PNG) +Apart from input parameter, you can also use checkboxes to enable/disable one or more below options +
**Also scan subscription controls:** Switch to scan subscription security controls. This will require Azure Connection (SPN) to have atleast 'Reader' access at the subscription scope and ‘Contributor’ access on the ‘AzSKRG’ resource group. +
**Send events to Log Analytics:** Switch to enable this task to publish SVT evaluation results to a Log Analytics workspace. Steps to configure workspace credentials are explained in Step-4 +
**Aggregate control status:** Switch to aggregate the SVTs control output. When this is turned off it would show all the failed individual controls in the task summary output. +
**Do not auto-update AzSK:** Switch to toggle auto update of AzSK and required Az modules on the build server. Keep this un-checked for Hosted agent and Hosted VS2017 and while using SVT task fot the first time and if you want to update AZSK the version of AzSK. +![03_IP_Parameter_for_Task](../Images/03_IP_Parameters_for_Task.png) -**Step-4:** (Optional) Setup connectivity from CICD to OMS. +**Step-4:** (Optional) Setup connectivity from CICD to Log Analytics. > **Note:** You can skip this step in a first pass exploration of CICD integration of SVTs. -This feature enables you to route the control scan results from SVTs in CICD pipelines to an OMS workspace. -Configuring an OMS workspace for the AzSK_SVTs task basically enables monitoring capability for +This feature enables you to route the control scan results from SVTs in CICD pipelines to a Log Analytics workspace. +Configuring a Log Analytics workspace for the AzSK_SVTs task basically enables monitoring capability for build environments. Each time SVTs run in CICD, the AzSK events generated will be sent to -the OMS repository and become available for subsequent queries, actions, alerts, etc. in the OMS workspace. -(The AzSK includes an OMS solution that can be used to create a 'single dashboard' view of security +the Azure Monitor repository and become available for subsequent queries, actions, alerts, etc. in the Log Analytics workspace. +(The AzSK includes a Monitoring solution that can be used to create a 'single dashboard' view of security for one or more applications across multiple dev ops stages.) -Below, we have added config info of a trial OMS workspace used by the AzSK team. You should choose your -own target OMS workspace and the corresponding resource group instead. (You can use Get-AzureRmOperationalInsightsWorkspace -cmdlet to quickly find out the resource group corresponding to your OMS workspace. If you do not know your -app's OMS workspace, you should check with your monitoring lead. Else you can create a trial workspace with +We have added config info of a trial Log Analytics workspace used by the AzSK team below. You should choose your +own target Log Analytics workspace and the corresponding resource group instead. (You can use Get-AzOperationalInsightsWorkspace +cmdlet to quickly find out the resource group corresponding to your Log Analytics workspace. If you do not know your +app's Log Analytics workspace, you should check with your monitoring lead. Else you can create a trial workspace with the 'Free' tier option.) -The OMS workspace information may be provided using one of the two options below: +The Log Analytics workspace information may be provided using one of the two options below: **Option-1:** Use a 'variable group' -In this option, a single variable group may be defined at the VSTS level to represent the OMS workspace -that a collection of projects want to share. This variable group may be 'linked' from the individual +In this option, a single variable group may be defined at the VSTS level to represent the Log Analytics workspace +that a collection of projects wants to share. This variable group may be 'linked' from the individual build/release definitions across these projects. The benefit is that, in the future, if a key value changes, you just have to make that change in one place and all definitions will immediately reflect the change. The images below show this option. It involves 2 steps: -1. Create a variable group that holds the OMS info (if one doesn't exist for your org) +1. Create a variable group that holds the Log Analytics workspace info (if one doesn't exist for your org) 2. Link that variable group to your project's release definition The variable group name can be a unique name you can choose (and specify in the release task definition). The specific variable names for workspace ID and shared key have to be exactly as shown below. The values -of these should correspond the corresponding info for your OMS workspace. +of these should correspond the corresponding info for your Log Analytics workspace. Creating the variable group: -![03_Creating_Variable_Group](../Images/03_Creating_Variable_Group.png) +![03_Creating_Variable_Group](../Images/03_Creating_Variable_Group.PNG) Linking to the release definition: -![03_Linking_To_Release](../Images/03_Linking_To_Release.png) +![03_Linking_To_Release](../Images/03_Linking_To_Release.PNG) > **Note:** Variable groups can only be modified or added from the Library under VSTS instance. **Option-2:** Directly use variables in individual build definitions. -![03_Directly_Use_Variable](../Images/03_Directly_Use_Variable.png) +![03_Directly_Use_Variables](../Images/03_Directly_Use_Variables.png) Important: Ensure that the variable names used are exactly as above and the values correspond -to *your* OMS workspace. Moreover, when you specify the OMS shared key, click on the 'lock' icon +to *your* Log Analytics workspace. Moreover, when you specify the Log Analytics shared key, click on the 'lock' icon next to it so that it gets masked. -**Step-5:** Setup Online Policy URL -(You may skip this step in a first-pass exploration of CICD integration of SVTs and come back to it later when setting the extension up for a real project.) +**Step-5:** Setup Online Policy URL (Mandatory for Org policy users e.g. CSE users) + This feature enables you to set up the CICD task to use your organization's AzSK policies. -To use org-specific policies, you can get your org-specific url by (a) running Get-AzSKInfo -InfoType HostInfo and looking at the value of OnlinePolicyStoreUrl or (b) getting it from the AzSKSettings.json file on your machine under 'C:\Users\\AppData\Local\Microsoft\AzSK' folder. +To use org-specific policies, you can get your org-specific settings by (a) running Get-AzSKInfo -InfoType HostInfo and looking at the value of 'OnlinePolicyStoreUrl' and 'EnableAADAuthForOnlinePolicyStore'(it specifies whether Org policy URL 'AzSKServerURL' is protected by AAD authentication). -Below, we have added configuration info of 'AzSKServerURL' used by the AzSK team. The URL at your org can be different assuming there is an org-policy setup unique to your org. +Below, we have added configuration info of 'AzSKServerURL' and 'EnableServerAuth' used by the AzSK team. The URL at your org can be different assuming there is an org-policy setup unique to your org. The online policy URL can be configured for the CICD extension using one of the two options below: @@ -175,19 +206,21 @@ The variable group name can be a unique name you can choose (and specify in the The specific variable name for Policy URL has to be exactly as shown below. Creating the variable group: -![03_Online_Policy_Variable_Group](../Images/03_Online_Policy_Variable_Group.png) +![03_Online_Policy_Variable_Group](../Images/03_Online_Policy_Variable_Group.PNG) Linking to the release definition: -![03_Online_Policy_Linking_Release](../Images/03_Online_Policy_Linking_Release.png) +![03_Online_Policy_Linking_Release](../Images/03_Online_Policy_Linking_Release.PNG) > Note: Variable groups can only be modified or added from the Library under VSO instance. **Option-2**: Directly use variables in individual build definitions. -![03_Online_Policy_Directly_Use_Variable](../Images/03_Online_Policy_Directly_Use_Variable.png) +![03_Online_Policy_Directly_Use_Variables](../Images/03_Online_Policy_Directly_Use_Variables.png) **Step-6**: Save the Release Definition. ![03_Save_Release_Definition](../Images/03_Save_Release_Definition.PNG) +> **Note:** Please make sure that the service principal (SPN) that is used for the CICD pipeline task has the following permissions: (a) ‘Reader’ access on the resource groups that are to be scanned (or ‘Reader’ access at subscription level if all resource groups are being scanned) and (b) ‘Contributor’ access on the ‘AzSKRG’ resource group. +
The first permission is required so that the SVTs can scan resources for security issues successfully and the second permission is requires so that any past attestations for controls are respected by the scan. [Back to top...](Readme.md#contents) ### Verifying that the SVTs have been added and configured correctly @@ -195,25 +228,25 @@ Linking to the release definition: This can be done by adding a new release for an existing build (or trigger a new release via a minor/trial check-in). -![03_Start_Release_Pipeline](../Images/03_Start_Release_Pipeline.png) +![03_Start_Release_Pipeline](../Images/03_Start_Release_Pipeline.PNG) **Step-2:** Verify that the release pipeline has started. Once the release is triggered, we can see that it is in progress by clicking on "Releases" (or via "Build & Release" menu in the VSTS menu). -![03_Verify_Pipeline](../Images/03_Verify_Pipeline.png) +![03_Verify_Pipeline](../Images/03_Verify_Pipeline.PNG) **Step-3:** View the release outcome. In a few minutes the release pipeline should complete and we can view the outcomes as shown below (in the pic below we can see that the release pipeline has failed): -![03_View_Release_OutCome](../Images/03_View_Release_OutCome.png) +![03_View_Release_OutCome](../Images/03_View_Release_OutCome.PNG) **Step-4:** Look at the "Issues" to see why the release failed. The summary output shows the cause of failure (in this case it is because the AzSK SVTs have failed). -![03_Issues_Release_Fail](../Images/03_Issues_Release_Fail.png) +![03_Issues_Release_Fail](../Images/03_Issues_Release_Fail.PNG) **Step-5:** Look at the complete output log of the AzSK portion of the release pipeline execution . Clicking on the "Security controls are failing" text (in the pic above) and, further, clicking on @@ -222,7 +255,7 @@ Notice how the output is the same as what is displayed when SVTs are manually ru Essentially, the AzSK_SVTs extension gives us the capability to mirror the secure configuration state that was established during the development/prototyping phases. -![03_Release_Task](../Images/03_Release_Task.png) +![03_Release_Task](../Images/03_Release_Task.PNG) **Step-6:** See the summary "CSV" and detailed "LOG" output files for the AzSK SVTs. This is no different than the "ad hoc SVT run" scenarios. Note, above, how the SVT outputs the location @@ -251,13 +284,18 @@ that are supported by the VSTS task: |Variable Name| Usage| Examples| |-------------|------|---------| -|OMSWorkspaceID| Log analytics workspace to continuously monitor progressive release/deployment health| e.g. c18xxxxx-xxxx-abcd-efgh-12345613489c Refer to step-4 in the above section| -|OMSSharedKey| Log analytics workspace sharedkey for extension to push the scan results from CICD| Refer step-4 from the above section for detail steps| +|LAWSId| Log Analytics workspace to continuously monitor progressive release/deployment health| e.g. c18xxxxx-xxxx-abcd-efgh-12345613489c Refer to step-4 in the above section| +|LAWSSharedKey| Log Analytics workspace shared key for extension to push the scan results from CICD| Refer step-4 from the above section for detail steps| |AzSKServerURL| Org policy url for hosting the central policy configuration| Refer step-5 from the above section for detail steps | |EnableServerAuth| Specifies whether Org policy URL (AzSKServerURL) is protected by AAD authentication.| e.g. true - protected by AAD authentication, false - not protected by AAD authentication| |AzSKVersion| You could specify which version of toolkit you want to use in your CICD scan. And version specified should be >= N-2 where N is latest prod version. If variable is not provided, it uses the latest version available| e.g. 2.8.1| -|AzSKModuleName| This variable enable use to participate in the Preview testing. If you want to participate in preview, Provide the module name as "AzSKPreview". If not used, it would by default uses AzSK as module name| e.g. AzSKPreview| -|ExtendedCommand| Enables you to provide other switches supported by the Get-AzSKAzureServicesSecurityStatus command to perform focused scanning in the CICD pipeline | e.g. -ControlIds "Azure_Storage_DP_Encrypt_In_Transit,
Azure_Storage_DP_Encrypt_At_Rest_Blob" or -UseBaselineControls| +|AzSKModuleName| This variable enable users to participate in the Preview testing. If you want to participate in preview, Provide the module name as "AzSKPreview". If not used, it would by default uses AzSK as module name| e.g. AzSKPreview| +|ExtendedCommand| Enables you to provide other switches supported by the Get-AzSKAzureServicesSecurityStatus command to perform focused scanning in the CICD pipeline | e.g. -ControlIds "Azure_Storage_DP_Encrypt_In_Transit,
Azure_Storage_DP_Encrypt_At_Rest_Blob" or -UseBaselineControls. More switches that can be used with ExtendedCommand can be found [here](../02-Secure-Development/Readme.md#security-verification-tests-svt). | +|ExtendedCommandGSS| This variable is applicable when "Also scan subscription controls" option is enabled. It will enable you to provide additional parameters supported by the Get-AzSKSubscriptionSecurityStatus command to perform focused scanning in the CICD pipeline. ( Default implementation of GSS command in the task uses -ExcludeTags "OwnerAccess, GraphRead")| e.g. -FilterTags "AuthZ, BCDR" or -ControlIds "Azure_Subscription_Config_Azure_Security_Center". More switches that can be used with ExtendedCommandGSS can be found [here](../01-Subscription-Security/Readme.md#target-specific-controls-during-a-subscription-health-scan). | +|TreatAsPassed| This variable is to provide users with more control over behavior of the SVT extension in case of various control statuses other than ‘Passed’ or ‘Failed’. For e.g., using this, one may choose to have the extension treat statuses such as 'Verify','Manual','Exception' or 'Remediate' as 'Passed'.|e.g. The value of the variable TreatAsPassed can be passed as Verify,Manual to skip Verify and Manual controls| +|ScanOwnerAccessControlsGRS|This variable is to provide users with more control over scanning controls that need owner priviledges. With latest CICD task version 4.0.4, such controls are excluded from service controls scanby default.This behaviour can be overwritten by setting ScanOwnerAccessControlsGRS value to True. However, it is recommended not to give owner permissions to SPN over a subscription .| e.g. true +|UsageTelemetryLevel|This variable is to provide users with more control over sending anonymous telemetry for CICD scan at AzSK side. With latest CICD task version, if this variable is set to None , anonymous telemetry would not be captured at AzSK side.| e.g. Anonymous ,None + [Back to top...](Readme.md#contents) @@ -267,7 +305,7 @@ that are supported by the VSTS task: - Go to ‘AzSK_SVTs’ task in your release definition. - Make sure that the check box ‘Do not auto-update AzSK’ is unchecked. This will ensure to run the AzSK scan using the latest module from PS Gallery. -This error typically occurs when AzSK scan identifies non-compatible AzureRm and AzSK modules present on the machine and tries to install the latest ones. +This error typically occurs when AzSK scan identifies non-compatible Az and AzSK modules present on the machine and tries to install the latest ones. #### I have enabled AzSK_SVTs task in my release pipeline. It is taking too much time every time I queue a release, how can I reduce that time? - Go to ‘AzSK_SVTs’ task in your release definition. @@ -276,7 +314,30 @@ This error typically occurs when AzSK scan identifies non-compatible AzureRm and > **Note:** For Non-Hosted agent, it is always recommended to check if latest AzSK module is present on your machine before marking 'Do not auto-update AzSK' CheckBox as checked, since scan should always use latest AzSK module. > **Note:** You will need to keep the above checkbox unchecked if you are running the AzSK_SVTs task on any release agent for the first time OR you are running the task on Hosted VS2017 agent OR if non-hosted agent is already running on latest version. +#### I have enabled AzSK_SVTs task in my release pipeline. I am getting an error 'Cannot bind argument to parameter 'String' because it is null.' + +This error is occurring because some of the configurations are missing/incorrect. Please ensure you have selected the correct subscription/service principal in the drop-down list. + +If your subscription is not listed or if you want to use an existing service principal, you can setup an Azure service connection using the 'Add' or 'Manage' button. Managed Service Identity service connection scope is limited to access granted to the Azure virtual machine running the agent. Ensure that the VM has access to specified resources. + +#### I have enabled AzSK_SVTs task in my release pipeline. I am getting an error 'Could not perform AzSK SVTs scan. Please check if task configurations are correct.' + +This release fails with the below error message because one or more variables of the release pipeline is missing/incorrect. Make sure the value of AzSKServerURL and EnableServerAuth in the ‘Variables’ section of the pipeline is correctly set. + +- Run the command Get-AzSKInfo -InfoType HostInfo. +- The value of OnlinePolicyStoreURL and EnableAADAuthForOnlinePolicyStore should be used for the variable AzSKServerURL and EnableServerAuth in the variables section of the release pipeline. + +#### Why AzSK_SVTs task in my release pipeline has suddenly started failing 'Verify'/'Manual'/'Remediate'/'Exception' controls? + All the control statuses other than 'Passed' would be treated as 'Failed' in the AzSK_SVT Task(going forward from AzSK_SVTs version 3.0.3). To treat control statuses other than 'Failed' as 'Passed' you can use 'TreatAsPassed' variable. Refer this [link](Readme.md#advanced-cicd-scanning-capabilities) + +#### I want to run AzSK_SVT on non-hosted agent. What are the pre-requisites for running AzSK_SVTs task on non-hosted agent? +If you are using non-hosted agents you need to have azureps installed on it for AzSK_SVTs to run. +Make sure you have latest version of AzSK installed on the machine,since scan should always use latest AzSK module. + +#### Why attestation is not getting respected in AzSK_SVT task in CICD pipeline? +To read attestation data the context from which AzSK SVT command is run must have atleast 'Contributor' access on the AzSKRG resource group. So if you want your task to respect the attestation data you must give the CICD SPN contributor access on AzSKRG. + [Back to top...](Readme.md#contents) # Security Verification Tests (SVTs) in Jenkins pipeline (Preview) @@ -291,9 +352,9 @@ Currently AzSDK CICD extension/plugin has not been published on Jenkins reposito Go to Home Page --> Manage Jenkins --> Manage plugins --> Select Advanced --> Upload plugin file "[AzSDK_CICD_Jenkins_Plugin.hpi](Assets/AzSDK_CICD_Jenkins_Plugin.hpi)" -![03_Upload_plugin](../Images/03_Upload_Plugin.png) +![03_Upload_plugin](../Images/03_Upload_Plugin.PNG) -![03_Install_plugin](../Images/03_Install_Plugin.png) +![03_Install_plugin](../Images/03_Install_Plugin.PNG)
Plugin is successfully imported. Now let's use plugin to scan Azure Resources. [Back to top...](Readme.md#contents) @@ -321,38 +382,38 @@ This part assumes that you are familiar with Jenkins pipeline at a basic level. Click on "Add build step" and select "AzSK Security Verification Tests". - ![03_Add_Build_Steps](../Images/03_Add_Build_Steps.png) + ![03_Add_Build_Steps](../Images/03_Add_Build_Steps.PNG) - #### Step-4: Specify the input parameters for the SVT step. Step displays some configuration inputs that are required for the task to run. Specify SPN credentials id as configured in Step-1. Remaining inputs are none other than the familiar options we have been specifying while running the AzSK SVTs manually. When the pipeline executes, SVTs will scan the specified set of resources. - ![03_Input_Parameter](../Images/03_Input_Parameter.png) -- #### Step-5: (Optional) Setup connectivity from CICD to OMS. - You can also configure build to send runtime security evaluation results to OMS workspace. For that configure OMS credetial using below steps: - - For adding OMS workspace credentials + ![03_Input_Parameter](../Images/03_Input_Parameter.PNG) +- #### Step-5: (Optional) Setup connectivity from CICD to Log Analytics. + You can also configure build to send runtime security evaluation results to Log Analytics workspace. For that configure the credentials using below steps: + - For adding Log Analytics workspace credentials Go to Home Page --> Credentials --> System --> Global credentials --> Click on "Add Credentials" --> Select credential type "OMS Details" - Provide OMS details and click Ok + Provide the details and click Ok - ![03_Create_OMS](../Images/03_Create_OMS.png) + ![03_Create_OMS](../Images/03_Create_OMS.PNG) - Provide OMS Credentials Id in build step - ![03_Provide_OMS_Cred](../Images/03_Provide_OMS_Cred.png) + ![03_Provide_OMS_Cred](../Images/03_Provide_OMS_Cred.PNG) - #### Step-6: Save the Job - ![03_Save_Job](../Images/03_Save_Job.png) + ![03_Save_Job](../Images/03_Save_Job.PNG) [Back to top...](Readme.md#contents) ### Verifying that the SVTs have been added and configured correctly - #### Step-1: Trigger the build. - ![03_Trigger_Build_1](../Images/03_Trigger_Build_1.png) -- #### Step-2: Verify that the build has started. + ![03_Trigger_Build_1](../Images/03_Trigger_Build_1.PNG) + - #### Step-2: Verify that the build has started. - ![03_Trigger_Build_2](../Images/03_Trigger_Build_2.png) + ![03_Trigger_Build_2](../Images/03_Trigger_Build_2.PNG) - #### Step-3: View the 'Console Output'. - ![03_Trigger_Build_3](../Images/03_Trigger_Build_3.png) + ![03_Trigger_Build_3](../Images/03_Trigger_Build_3.PNG) - #### Step-4: See the summary "CSV" and detailed "LOG" output files for the AzSK SVTs. This is no different than the "ad hoc SVT run" scenarios. SVT outputs the location @@ -364,15 +425,466 @@ This part assumes that you are familiar with Jenkins pipeline at a basic level. > - Currently task is configured to not stop if SVT fails. ### Remediating failures and next steps -Once you have the CSV file and the LOG file for the SVTs execution, the process of understanding and -remediating failures is no different than what is used when SVTs are run manually. Basically, you will -need to look at the failed SVTs in the CSV file and the corresponding details about 'what exactly caused +Once you have the CSV file and the LOG file for the SVTs execution, the process of understanding and remediating failures is no different than what is used when SVTs are run manually. Basically, you will + need to look at the failed SVTs in the CSV file and the corresponding details about 'what exactly caused each individual failure?' in the LOG file. Thereafter the issue can be remediated (additional guidance available from AzSK is at the link in the CSV file for each row). -If you chose to route events to OMS, you can also use the AzSK Solution Pack for OMS to view things +If you chose to route events to Log Analytics, you can also use the AzSK Monitoring Solution to view things like "build/release security health", long term trends, configure and receive alerts for various conditions (e.g., back to back SVT failures) etc. [Back to top...](Readme.md#contents) +# AzSK ARM Template Checker +### Overview + +The ARM Template security check script runs a scan on your given ARM Template to examine various conditions and configurations that need to be present in your ARM Template for secured resource deployment. + +[Back to top…](Readme.md#contents) +### Scan the security health of your ARM Template + +The ARM Template health check script can be run using the command below after replacing `` + with the path of your ARM Template +```PowerShell +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath +``` +The parameters used are: +- ARMTemplatePath – Path to ARM Template file or folder + +[Back to top…](Readme.md#contents) + +### Execute ARM Template Checker in Baseline mode +In 'baseline mode' a centrally defined 'control baseline' is used as the target control set for scanning. +The cmdlet below scans ARM Template in Baseline mode and generates a status report: +```PowerShell +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -UseBaselineControls + +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -UsePreviewBaselineControls + +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -UseBaselineControls -UsePreviewBaselineControls +``` + +### Execute ARM Template Checker for specific controls +The Get-AzSKARMTemplateSecurityStatus command now supports a switch 'ControlIds' to scan only specific controls in ARM Template. +The cmdlet below will only scan 'Azure_AppService_Deploy_Use_Latest_Version' and 'Azure_AppService_AuthN_Use_Managed_Service_Identity' controls for the provided ARM Template. +```PowerShell +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -ControlIds 'Azure_AppService_Deploy_Use_Latest_Version,Azure_AppService_AuthN_Use_Managed_Service_Identity' +``` + +### Execute ARM Template Checker excluding some controls from scan +The Get-AzSKARMTemplateSecurityStatus command now supports a switch 'ExcludeControlIds' to exclude ARM Template controls from getting scanned. +The cmdlet below will not scan 'Azure_AppService_Deploy_Use_Latest_Version' control for the provided ARM Template. +```PowerShell +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -ExcludeControlIds 'Azure_AppService_Deploy_Use_Latest_Version' +``` + + +### Execute ARM Template Checker for specific control severity +The Get-AzSKARMTemplateSecurityStatus command now supports a parameter 'Severity' to scan controls of specified severities. +The cmdlet below will not scan 'Azure_AppService_Deploy_Use_Latest_Version' control for the provided ARM Template. +```PowerShell +Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath -Severity "High , Medium" +``` + + +### ARM Template Checker - Control coverage + +ARM Template checker covers Baseline controls for following services: + +|FeatureName|Resource Type| +|-----------|-------------| +| AppService |Microsoft.Web/sites| +| CDN |Microsoft.Cdn/profiles| +| CosmosDB |Microsoft.DocumentDb/databaseAccounts| +| DataLakeStore |Microsoft.DataLakeStore/accounts| +| RedisCache |Microsoft.Cache/Redis| +| SQLDatabase |Microsoft.Sql/servers| +| Storage |Microsoft.Storage/storageAccounts| +| TrafficManager |Microsoft.Network/trafficmanagerprofiles| +| ServiceFabric |Microsoft.ServiceFabric/clusters| +| Kubernetes |Microsoft.ContainerService/ManagedClusters| +| LogicApps |Microsoft.Logic/workflows| +| ContainerRegistry |Microsoft.ContainerRegistry/registries| +| KeyVault |Microsoft.KeyVault/vaults| +| VirtualNetwork |Microsoft.Network/virtualNetworks| +| Search |Microsoft.Search/searchServices| +| EventHub |Microsoft.EventHub/namespaces| +| ContainerInstances |Microsoft.ContainerInstance/containerGroups| +| HDInsight |Microsoft.HDInsight/clusters| +| APIManagement |Microsoft.ApiManagement/service| +| PostgreSQL |Microsoft.DBforPostgreSQL/servers| +| MySQL |Microsoft.DBforMySQL/servers| +| Analysis Services |Microsoft.AnalysisServices/servers| + +ARM Templates for reference are available [here](../ARMTemplates). + +### ARM Template Checker Scan - How to fix findings? + +Get-AzSKARMTemplateSecurityStatus cmdlet generate outputs which are organized as under: +- summary information of the control evaluation (pass/fail) status in a CSV file, +- detailed powershell output log in a LOG file + +To address findings, you should do the following: +1. See the summary of control evaluation first in the CSV file. (Open the CSV in XLS. Use "Format as Table", "Hide Columns", "Filter", etc.) +2. Review controls that are marked as "Failed", "Verify" or "Manual" +3. Use the following approach based on control status: + - For the “Verify” controls, look at the expected property, expected value and description column in .CSV file to decide whether to consider the control as "Passed" or not. + - For the “Failed” controls, look at the .CSV file to get the supporting information like expected property, expected value, line no. and resource path etc. +> **Note**: If 'ExpectedProperty' column in .CSV file contains multiple properties (for e.g. $.properties.siteConfig.alwaysOn | $.properties.alwaysOn), in this case you only need to provide expected value in anyone of these properties to fix the failed control. + +#### Scan multiple ARM Templates :- +To scan multiple ARM Templates at a time you can pass folder path containing different ARM Template(s) to “–ARMTemplatePath” parameter in “Get-AzSKARMTemplateSecurityStatus” cmdlet. +e.g. : +```PowerShell + Get-AzSKARMTemplateSecurityStatus –ARMTemplatePath "D:\DSRE\TestARMChecker\" [-Recurse] +``` +> **Note**: You need to pass “-Recurse” switch in cmdlet if you want to scan ARM Templates in the specified location and in all child folders of the location. + +[Back to top...](Readme.md#contents) + +### Enable AzSK extension for your VSTS + +This extension has been published to the VSTS gallery under "Build and Release" category. +You can now install this extension from the Marketplace directly (https://marketplace.visualstudio.com/items?itemName=azsdktm.AzSDK-task). +> **Note:** You can also install this extension on your on-prem TFS instance. Please follow the instructions detailed at: +> https://docs.microsoft.com/en-us/vsts/marketplace/get-tfs-extensions + +### Walkthrough +This part assumes that you are familiar with VS build tasks and pipelines at a basic level. To demonstrate +the capability of the feature, we will use a basic ARMTemplate that is checked into our trial repository. +Our goal is to show how ARM checker can be injected into the build/release workflow so that security testing for +Azure resources can be done before deployment of ARM Template seamlessly in CICD. + +[Back to top...](Readme.md#contents) + +### Adding ARM Template Checker in VSTS pipeline + +**Step-1:** Create a release definition or open an existing one. +As shown below, currently the release definition is configured to simply deploy a ARM Template using Azure Powershell script. This is likely to be the state of any working CICD pipeline that deploys a ARM Template from VSTS to an Azure subscription. + +Let us take a look at the steps needed to add the AzSK-ARM Template Checker task to the release definition. + +![03_Create_Release_Definition](../Images/03_Create_Release_Definition_ARM.JPG) + +**Step-2:** Add the AzSK-ARM Template Checker release task to the pipeline. +Click on "Add Tasks", and select "AzSK ARM Template Checker". +Click on "Add" and "Close". +> **Note:** The VSTS dialog doesn't provide a good visual indication but the task does +get added when you click "Add" once! + +![03_Task_Catalog](../Images/03_Task_Catalog_ARM.JPG) + +**Step-3:** Specify the input parameters for the ARM Checker task. +The "AzSK ARM Template Checker" task starts showing in the "Run on Agent" list and displays some configuration inputs that are required for the task to run. These are none other than the familiar options we have been specifying while running the AzSK ARM Template Checker manually - you can specify the target ARM Template file path or a folder path based on your requirement. + +Along with input parameter, you can check for below options +
**Recurse:** Switch this if you want to scan ARM Templates in the specified location and in all child folders of the location. +
**Do not auto-update AzSK:** Switch to toggle auto update of AzSK and required Az modules on the build server. Keep this un-checked for Hosted agent and Hosted VS2017 and while using SVT task fot the first time and if you want to update AZSK the version of AzSK. + +![03_IP_Parameter_for_Task](../Images/03_IP_Parameter_for_Task_ARM.JPG) + +**Step-4**: Specify AzSKServerURL and EnableServerAuth variables if you want to use your own org-policy. Please follow this [link](../07-Customizing-AzSK-for-your-Org#how-does-azsk-use-online-policy) to understand how does AzSK use online policy. + +AzSKServerURL -> AzSK OnlinePolicyStoreUrl + +EnableServerAuth -> EnableAADAuthForOnlinePolicyStore + +![ARMChecker_Orgpolicy_Variables](../Images/ARMChecker_Orgpolicy_Variables.jpg) + +**Step-5**: Save the Release Definition. + +[Back to top...](Readme.md#contents) + +### Verifying that the ARM Template Checker have been added and configured correctly +**Step-1:** Start the release pipeline. +This can be done by adding a new release for an existing build (or trigger a new release via a minor/trial +check-in). + +![03_Start_Release_Pipeline](../Images/03_Start_Release_Pipeline_ARM.JPG) + +**Step-2:** Verify that the release pipeline has started. +Once the release is triggered, we can see that it is in progress by clicking on "Releases" (or via +"Build & Release" menu in the VSTS menu). + +![03_Verify_Pipeline](../Images/03_Verify_Pipeline_ARM.JPG) + +**Step-3:** View the release outcome. +In a few minutes the release pipeline should complete and we can view the outcomes as shown below (in the +pic below we can see that the release pipeline has failed): + +![03_View_Release_OutCome](../Images/03_View_Release_OutCome_ARMChecker.png) + +**Step-4:** Look at the "Issues" to see why the release failed. +The summary output shows the cause of failure (in this case it is because the AzSK ARM Template Checker have failed). + + +![03_Issues_Release_Fail](../Images/03_Issues_Release_Fail_ARM.JPG) + +**Step-5:** Look at the complete output log of the ARM Checker portion of the release pipeline execution . Notice how the output is the same as what is displayed when ARM Template Checker cmdlet manually run in a PS console. + +![03_Release_Task](../Images/03_Release_Task_ARM.JPG) + +**Step-6:** See the summary "CSV" and detailed "LOG" output files for the AzSK_ARMTemplateChecker. +This is no different than the "ad hoc ARM Template Checker run" scenarios. Note, above, how the ARM Template Checker outputs the location of the "CSV" file and the "LOG" file at the end of the run. However, those locations are on the release +agent machine. These are also packaged up in an overall ZIP file and are available to download. The +overall ZIP file can be downloaded by clicking on the "Download all logs as ZIP" option. +The ZIP file "ReleaseLogs_dd.zip" contains LOGs from the entire release pipeline including the master +output for the AzSK_ARMTemplateChecker. The CSV file and the LOG file for AzSK ARM Template Checker are embedded in the 'inner' ZIP +file that is named as ArmTemplateChecker_Logs_yyyymmdd_hhmmss.zip . + +![03_Output_Folder](../Images/03_Output_Folder_ARM.JPG) + +Opening/extracting the "ArmTemplateChecker_Logs" ZIP file will reveal a folder structure and files placement identical to +what we have seen in the case of ad hoc ARMChecker runs: +![03_AzSDK_Logs](../Images/03_ARMChecker_Logs.JPG) + +[Back to top...](Readme.md#contents) + +### Exclude files from scan +To scan multiple ARM Templates at a time you can pass folder path containing different ARM Template(s) but it is possible that folder may contain some ARM Template(s) that are not valid or currently not supported by ARM Checker. In this case AzSK ARM Template Checker Task will skip those file(s) and will fail. + +![03_SkippedFile_Error_ARMChecker](../Images/03_SkippedFile_Error_ARMChecker.JPG) +The overall ZIP file can be downloaded by clicking on the "Download all logs as ZIP" option. The ZIP file "ReleaseLogs_dd.zip" contains LOGs from the entire release pipeline including the master output for the AzSK_ARMTemplateChecker. The CSV file and the LOG file for AzSK ARM Template Checker are embedded in the 'inner' ZIP file that is named as ArmTemplateChecker_Logs_yyyymmdd_hhmmss.zip . Download "ArmTemplateChecker_Logs" ZIP file and then Open/extract the "ArmTemplateChecker_Logs". It will contains SkippedFiles.LOG file along with other files. On opening this file you will get list of all file(s) skipped during scan. + +![03_Skipped_Files_Log_ARMChecker](../Images/03_Skipped_Files_Log_ARMChecker.JPG) + +In such case you can exclude files from scan using "Exclude Files" input, you need to pass name of the files (comma separated) you want to exclude in "Exclude Files" input as shown in image below: + +![03_ExcludeFiles_Param_ARMChecker](../Images/03_ExcludeFiles_Param_ARMChecker.JPG) + +[Back to top...](Readme.md#contents) + +### Skip certain controls during scan + +AzSK ARM Template Checker will fail if any security control will fail for provided ARM Template. But in some case it may be possible that some controls failure you don't want to fix. In such case you can skip specific controls from scan using below step:
+**Step-1:** The overall ZIP file can be downloaded by clicking on the "Download all logs as ZIP" option. The ZIP file "ReleaseLogs_dd.zip" contains LOGs from the entire release pipeline including the master output for the AzSK_ARMTemplateChecker. The CSV file and the LOG file for AzSK ARM Template Checker are embedded in the 'inner' ZIP file that is named as ArmTemplateChecker_Logs_yyyymmdd_hhmmss.zip . Opening/extracting the "ArmTemplateChecker_Logs" ZIP file will reveal a folder structure and files placement as shown below: + +![03_ARMChecker_Logs](../Images/03_ARMChecker_Logs.JPG) + +**Step-2:** Open CSV file and start editing, keep only those controls with failed status which you want to skip from scan. + +![03_FailedControl_Logs_ARMChecker](../Images/03_FailedControl_Logs_ARMChecker.JPG) + +After editing CSV should look like this, + +![03_Skip_Controls_File_ARMChecker](../Images/03_Skip_Controls_File_ARMChecker.JPG) + +**Step-3:** Upload this edited CSV file to your repository and give path of this file in "Skip Controls From File" input as shown in below image: + +![03_Skip_Controls_Param_ARMCheckerJPG](../Images/03_Skip_Controls_Param_ARMCheckerJPG.JPG) + +[Back to top...](Readme.md#contents) + +### Use external parameter file + +To pass parameter values while scanning your ARM Template by ARM Checker, you can use external parameter file. The parameter file contains a value for the parameter. This value is automatically passed to the template during scanning. +To pass external paramter file, give path of this file in "Parameter file path or folder path" input as shown in below image: + +![03_Use_ParamFiles_ARMCheckerJPG](../Images/03_Use_ParamFiles_ARMCheckerJPG.jpg) + +> **Note:** If you are passing folder path instead of single parameter file path, then parameter file must follow specific naming convention, [Template file name].parameters.json
+> for e.g.
+> ARM template file name - storage.json
+> Related parameter file name- storage.parameters.json + +[Back to top...](Readme.md#contents) + +### Advanced CICD scanning capabilities +DevOps kit CICD extension enables you to leverage all the advance capabilities of toolkit while running in adhoc mode. +You could scan for specific controlIds in your build pipeline, or you could exclude some controls from scan, +or you could also run a specific version of kit etc. +These advance features are available to customers through VSTS variables. Table below provide the different variables +that are supported by the ARM Checker task: + +|Variable Name| Usage| Examples| +|-------------|------|---------| +|AzSKServerURL| Org policy url for hosting the central policy configuration| Refer step-5 from the [above section](Readme.md#adding-svts-in-the-release-pipeline) for detail steps | +|EnableServerAuth| Specifies whether Org policy URL (AzSKServerURL) is protected by AAD authentication.| e.g. true - protected by AAD authentication, false - not protected by AAD authentication| +|AzSKVersion| You could specify which version of toolkit you want to use in your CICD scan. And version specified should be >= N-2 where N is latest prod version. If variable is not provided, it uses the latest version available| e.g. 3.12.0| +|AzSKModuleName| This variable enable users to participate in the Preview testing. If you want to participate in preview, Provide the module name as "AzSKPreview". If not used, it would by default uses AzSK as module name| e.g. AzSKPreview| +|ExtendedCommand| Enables you to provide other switches supported by the Get-AzSKARMTemplateSecurityStatus command to perform focused scanning in the CICD pipeline | e.g. -ControlIds "Azure_AppService_Deploy_Use_Latest_Version,
Azure_AppService_AuthN_Use_Managed_Service_Identity" or -UseBaselineControls or -Severity "High, Medium" +|TreatAsPassed| This variable is to provide users with more control over behavior of the SVT extension in case of various control statuses other than ‘Passed’ or ‘Failed’. For e.g., using this, one may choose to have the extension treat statuses such as 'Verify','Manual' as 'Passed'.|e.g. The value of the variable TreatAsPassed can be passed as Verify,Manual to skip Verify and Manual controls| +|FailTaskIfNoControlsScanned| This variable is to control the behavior of the SVT extension in case of no controls scanned. For e.g., using this, one may choose to pass the task if it is configured to scan only 'High' severity control but there are no resources for which 'High' severity controls are applicable.| e.g. The value of the variable 'FailTaskIfNoControlsScanned' can be passed as 'true' to fail the task if no controls scanned or 'false' to pass the task if no controls scanned| + +> **Note:** If you are using custom org policy features such as baseline controls scan etc., please make sure that CheckBox 'Use Org Baseline(s)' is checked and also provide an active azure service connection. + +### Extending ARM Template Checker for your organization + +If you are using [ org-policy ](../07-Customizing-AzSK-for-your-Org) feature, you can extend/customize the ARM Template Checker for your organization such as (a) by adding new controls to existing services or (b) by adding support to scan altogether new services. In this section, let us walk through the steps required to do so. However, before learning about extending ARM Template Checker, let us first understand how it works. + +### How ARM Checker scans a control + +To understand this, let's look at a single control for any service (e.g., Storage -> encrypt-in-transit control), +```json +{ +"featureName": "Storage", +"supportedResourceTypes": ["Microsoft.Storage/storageAccounts"], +"controls": [ + { + "id": "AzureStorage160", + "controlId": "Azure_Storage_DP_Encrypt_In_Transit_Test", + "isEnabled": true, + "description": "HTTPS protocol must be used for accessing Storage Account resources", + "rationale": "Use of HTTPS ensures server/service authentication and protects data in transit from network layer man-in-the-middle, eavesdropping, session-hijacking attacks. When enabling HTTPS one must remember to simultaneously disable access over plain HTTP else data can still be subject to compromise over clear text connections.", + "recommendation": "Run command 'Set-AzStorageAccount -ResourceGroupName -Name -EnableHttpsTrafficOnly `$true'. Run 'Get-Help Set-AzStorageAccount -full' for more help.", + "severity": "Medium", + "jsonPath": ["$.properties.supportsHttpsTrafficOnly"], + "matchType": "Boolean", + "data": {"value": true} + } + ] +} +``` + +Once you pass ARM Template file to ARM Checker for scanning, while scanning ARM Template it follows steps mentioned below: + +1. First of all, ARM Checker checks if the services used in the ARM template being scanned are supported by looking at the "SupportedResourceType" field in a file called “ARMControls.json” that is a global list of all services and corresponding controls covered by the ARM Checker. (It will look for this file in the folder “%userprofile%\Documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\ARMChecker\ARMControls.json”. For instance, for the above example, it will look for: "Microsoft.Storage/storageAccounts".) +> **Note:** If "ARMControls.json" file is present on your org-server, server file will override the file present in your local machine. + +2. For each service type that is covered, it will look under the “controls” list for that service type to identify the properties it needs to check for in the ARM template as mentioned by the “jsonPath” for each control (in our example, Microsoft.Storage/storageAccounts -> properties -> supportsHttpsTrafficOnly) +3. If the corresponding property is found on the object in the ARM template, it will compare with the expectation by using the “MatchType” and “Data” fields in the control. + * If the property is found and it's value matches with the value(s) specified in the "data" field (e.g., "True" above), ARM Checker will pass the control. + * If the property is not found, or its value doesn't match with expected value ARM Checker will fail the control. + +### How to add new controls to an existing service + +1. Edit ARMControls.json +2. Go to the service in which you want to add new controls +3. Add new control object in the "controls" array. + ``` json + { + "id": "TBD910", + "controlId": "TBD", + "isEnabled": true, + "description": "TBD", + "rationale": "TBD", + "recommendation": "TBD", + "severity": "High", + "jsonPath": [ "$.properties.properties1" ], + "matchType": "Boolean", + "data": { + "value": false + }  + } + ``` + +> **Note:** For control id, please use format like featureName + Integer (should be greater than 900) e.g. "id" : TrafficManager910 . + +#### Important properties in control object: +* "isEnabled" : To enable/disable control during scan. If set to 'false' control will not be scanned. +* "jsonPath": Path of the property/object in ARM Template which will be evaluated by ARM Checker.  +* "matchType": This field defines the type of property/object, expected at the path provided as "jsonPath" +* "data": This field determines control evaluation, different properties and values of those properties depends on the "matchType" defined above. + +#### Supported Match type and their respective Data type: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MatchTypeData.TypeData.ValueData.IsCaseSensitiveDescriptionExample
BooleanNAtrue/falseNAProperty should be present at "JsonPath", Property value should be a boolean and matches the value as mentioned in "data.value"If we want to ensure, in App Service "remote debugging" should be turned off,
"jsonPath": [ "$.properties.siteConfig.remoteDebuggingEnabled"]
"matchType": "Boolean",
"data": {
"value": false
}
IntegerValueGreaterThan/LesserThan/Equals< Any integer value >
NAProperty should be present at "JsonPath", Property value should be a integer and Property value should be "GreaterThan/LesserThan/Equals" ( as mentioned in "data.type" ) to value (as mentioned in "data.value")
If we want to ensure, App Service must be deployed on a minimum of two instances,
"jsonPath": [ "$.sku.capacity" ],
"matchType": "IntegerValue",
"data": {
"type": "GreaterThan",
"value": 1
}
ItemCountGreaterThan/LesserThan/Equals< Any integer value >
NAProperty should be present at "JsonPath", Property value should be an Array and Count of object in Array should be "GreaterThan/LesserThan/Equals" ( as mentioned in "data.type" ) to value (as mentioned in "data.value")
If we want to ensure, CosmosDB uses replication,
"jsonPath": [ "$.properties.locations" ],
"matchType": "ItemCount",
"data": {
"type": "GreaterThan",
"value": 1
}
StringWhitespaceNAfalse/true
NAProperty should be present at "JsonPath" and Property value should be "Empty string " or "Non empty String" (as mentioned in "data.value" )
If we want to ensure, App Service must authenticate users using AAD backed credentials
"jsonPath": [ "$.properties.siteConfig.siteAuthSettings.clientId"],
"matchType": "StringWhitespace",
"data": { +
"value": false + }
StringSingleTokenAllow/NotAllow< Any string value >
false/true
Property should be present at "JsonPath", Property value should be string and Property value should be "equal to (Allow)" or "not to equal(Not Allow)" (as mentioned in "data.type" )
If we want to ensure, latest version of .NET framework version must be used for App Service
"jsonPath": [ "$.properties.siteConfig.netFrameworkVersion"],
"matchType": "StringSingleToken",
"data": { +
"type": "Allow", +
"value": "v4.7", +
"isCaseSensitive": false + }
VerifiableSingleTokenNANANAProperty should be present at "JsonPath" and Property value should be string
If we want to ensure, only the required IP addresses are configured on Cosmos DB firewall
"jsonPath": [ "$.properties.ipRangeFilter" ],
"matchType": "VerifiableSingleToken",",
"data": {}
+ +### How to add a new service + +1. Edit ARMControls.json +2. Add new Service object in "resourceControlSets" array like, + ```json + { + "featureName": "NewServiceName", + "supportedResourceTypes": [ "Microsoft.XYZ/abc" ], + "controls": [ ] + } + ``` + E.g. + ```json + { + "featureName": "ContainerRegistry", + "supportedResourceTypes": [ "Microsoft.ContainerRegistry/registries" ], + "controls": [] + } + + ``` +> **Note:** Resource type defined in "supportedResourceTypes" must be exactly same as resource type present in ARM template of the service. + +If a service contains multiple resource type, you can add multiple types in "supportedResourceTypes" array. + E.g. + +"supportedResourceTypes": [ "Microsoft.Web/sites", "Microsoft.Web/serverfarms", "Microsoft.Web/sites/config" ] + +### Uploading extended ARM controls to policy store + +Once you have tested your new ARM Checker controls on your machine.You need to upload these new controls to org policy store so that these new controls will be available for all users in your organization. + +1. Go to org policy folder(in your local machine) +2. Create ARMControls.ext.json file with content given below.(if not present already) + + ```json + { + "resourceControlSets": [ ] + } + ``` + +3. If you have added new service in ARM Checker, copy the whole service object (with all controls) from ARMControls.json and add it to "resourceControlSets" in ARMControls.ext.json file. +4. If you have extended controls in any existing service in ARM Checker, copy the service object (with only new controls) from ARMControls.json and add it to "resourceControlSets" in ARMControls.ext.json file. +5. Run Update-AzSKOrganizationPolicy command to upload ARMControls.ext.json file to policy store. + diff --git a/04-Continous-Assurance/Readme.md b/04-Continous-Assurance/Readme.md index ee2eb387..6271e7a8 100644 --- a/04-Continous-Assurance/Readme.md +++ b/04-Continous-Assurance/Readme.md @@ -1,26 +1,40 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + +>NOTE: +>The OMS* parameter/variable names will soon be deprecated. Please ensure that you have made the necessary changes to CA, CICD and AzSK Monitoring Solution as per below: +> 1. Updated CA setups with new names ([details here](../04-Continous-Assurance#updating-an-existing-continuous-assurance-setup)). (Not required for CSEO subscriptions!) +> 2. Switched to new names in CICD extension ([details here](../03-Security-In-CICD#advanced-cicd-scanning-capabilities)). (Required for all subscriptions) +> 3. Start using the new parameters for [CA](../04-Continous-Assurance#setting-up-continuous-assurance---step-by-step) and [AzSK Monitoring Solution](../05-Alerting-and-Monitoring#1-c). + # Continuous Assurance (CA) -![Continous_Assurance](../Images/Continous_Assurance.PNG) +![Continous_Assurance](../Images/Continous_Assurance.png) ## Baseline Continuous Assurance ### Contents - [Overview](Readme.md#overview) - [Setting up Continuous Assurance - Step by Step](Readme.md#setting-up-continuous-assurance---step-by-step) - [Continuous Assurance - how it works (under the covers)](Readme.md#continuous-assurance---how-it-works-under-the-covers) -- [Update existing Continuous Assurance Automation Account](Readme.md#update-existing-continuous-assurance-automation-account) -- [Remove Continuous Assurance Automation Account](Readme.md#remove-continuous-assurance-automation-account) -- [Fetch details of an existing Continuous Assurance Automation Account](Readme.md#fetch-details-of-an-existing-continuous-assurance-automation-account) -- [Continuous Assurance through central scanning mode (Preview) - Step by Step](Readme.md#continuous-assurance-through-central-scanning-mode-preview---step-by-step) +- [Updating an existing Continuous Assurance setup](Readme.md#updating-an-existing-continuous-assurance-setup) +- [Removing a Continuous Assurance setup](Readme.md#removing-a-continuous-assurance-setup) +- [Getting details about a Continuous Assurance setup](Readme.md#getting-details-about-a-continuous-assurance-setup) +- [Continuous Assurance (CA) - 'Central Scan' mode](Readme.md#continuous-assurance-ca---central-scan-mode) +- [Continuous Assurance (CA) - Trigger scan on resource deployment (Preview)](Readme.md#continuous-assurance-ca---scanondeployment-mode) +- [Scan Databricks using custom AzSK Job](Readme.md#scan-databricks-using-custom-azsk-job) - [FAQ](Readme.md#faq) ----------------------------------------------------------------- -### Overview +## Overview The basic idea behind Continuous Assurance (CA) is to setup the ability to check for "drift" from what is considered a secure snapshot of a system. Support for Continuous Assurance lets us treat security truly as a 'state' as opposed to a 'point in time' achievement. This is particularly important in today's context when 'continuous change' has become a norm. -There can be two types of drift: +There can be two types of drift: 1. Drift involving 'baseline' configuration: This involves settings that have a fixed number of possible states (often pre-defined/statically determined ones). For instance, a SQL DB can have TDE encryption turned ON or OFF…or a Storage Account may have @@ -40,38 +54,48 @@ you should run 'Install-AzSKContinuousAssurance' command again by following the [Back to top…](Readme.md#contents) -### Setting up Continuous Assurance - Step by Step +## Setting up Continuous Assurance - Step by Step In this section, we will walk through the steps of setting up a subscription and application(s) for Continuous Assurance coverage. To get started, we need the following: 1. The user setting up Continuous Assurance needs to have 'Owner' access to the subscription. (This is necessary because during setup, AzSK adds the service principal runtime account as a 'Reader' to the subscription.) -2. Target OMS WorkspaceID* and SharedKey. (The OMS workspace can be in a different subscription, see note below) +>**Note:** Starting AzSK v3.15.0, users having 'Contributor' permissions can set up AzSK Continuous Assurance (CA) for the subscription. The part of the setup where 'Owner' access is required will not abort if the user does not have that permission any more... instead, it will print a warning and ask the user to ensure that the required permissions are granted by someone (else) with 'Owner' access for the CA SPN (that does is used for the runtime scanning). Note that the CA SPN requires 'Reader' permission on the subscription and 'Contributor' permission on the DevOps Kit resource group in the subscription. CA will work seamlessly so long as these permissions are assigned (soon after the install cmdlet) by the owner. + +2. Target Log Analytics WorkspaceID* and SharedKey. (The Log Analytics workspace can be in a different subscription, see note below) +**Prerequisite:** -> **\*Note** CA leverages an OMS repository for aggregating security scan results, you must determine which OMS workspace -you will use to view the security state of your subscription and applications (If you don't have an OMS repository please -follow the steps in [Setting up the AzSK OMS Solution](../05-Alerting-and-Monitoring/Readme.md) ). +**1.** We currently support following OS options: +- Windows 10 +- Windows Server 2016 + + +> **\*Note** CA leverages Azure Monitor repository for aggregating security scan results, you must determine which Log Analytics workspace +you will use to view the security state of your subscription and applications (If you don't have a Log Analytics workspace please +follow the steps in [Setting up the AzSK Monitoring Solution](../05-Alerting-and-Monitoring/Readme.md#setting-up-the-azsk-monitoring-solution-step-by-step). This can be a single workspace that is shared by multiple applications which may themselves be in different subscriptions. -Alternately, you can have an OMS workspace that is dedicated to monitoring a single application as well. +Alternately, you can have a Log Analytics workspace that is dedicated to monitoring a single application as well. (Ideally, you should use the same workspace that is being used to monitor other aspects like availability, performance, etc. for your application.) **Step-1: Setup** -0. Setup the latest version of the AzSK following the installation instructions for your organization. (For MSIT use https://aka.ms/azsdkdocs). -1. Open the PowerShell ISE and login to your Azure account (using **Login-AzureRmAccount**). +0. Setup the latest version of the AzSK following the installation instructions for your organization. (For CSE use https://aka.ms/devopskit/onboarding). +1. Open the PowerShell ISE and login to your Azure account (using **Connect-AzAccount**). 2. Run the '**Install-AzSKContinuousAssurance**' command with required parameters given in below table. ```PowerShell Install-AzSKContinuousAssurance -SubscriptionId ` [-AutomationAccountLocation ] ` + [-AutomationAccountRGName ] ` + [-AutomationAccountName ] ` -ResourceGroupNames ` - -OMSWorkspaceId ` - -OMSSharedKey ` - [-AltOMSWorkspaceId ] ` - [-AltOMSSharedKey ] ` + -LAWSId ` + -LAWSSharedKey ` + [-AltLAWSId ] ` + [-AltLAWSSharedKey ] ` [-WebhookUrl ] ` [-WebhookAuthZHeaderName ] ` [-WebhookAuthZHeaderValue ] ` @@ -79,22 +103,42 @@ for your application.) [-AzureADAppName ] ``` +Here is one basic example of continuous assurnace setup command: + +```PowerShell + Install-AzSKContinuousAssurance -SubscriptionId ` + -ResourceGroupNames ‘rgName1, rgName2,…etc.’ ` # You can also use “*” to specify all RGs + -LAWSId ` + -LAWSSharedKey +``` + +Note: + +For Azure environments other than Azure Cloud, don't forget to provide AutomationAccountLocation as the default value won't work in those environments. + |Param Name|Purpose|Required?|Default value|Comments| |----|----|----|----|----| |SubscriptionId|Subscription ID of the Azure subscription in which an Automation Account for Continuous Assurance will be created |TRUE|None|| -|AutomationAccountLocation|(Optional) The location in which this cmdlet creates the Automation Account|FALSE|EastUS2|To obtain valid locations, use the Get-AzureRMLocation cmdlet| -|ResourceGroupNames|Comma separated list of resource groups within which the application resources are contained.|TRUE|None|| -|OMSWorkspaceId|Workspace ID of OMS which is used to monitor security scan results|TRUE|None|| -|OMSSharedKey|Shared key of OMS which is used to monitor security scan results|TRUE|None|| -|AltOMSWorkspaceId|(Optional) Alternate Workspace ID of OMS to monitor security scan results|FALSE|None|| -|AltOMSSharedKey|(Optional) Shared key of Alternate OMS which is used to monitor security scan results|FALSE|None|| +|AutomationAccountLocation|(Optional) The location in which this cmdlet creates the Automation Account|FALSE|EastUS2|To obtain valid locations, use the Get-AzLocation cmdlet| +|AutomationAccountRGName|(Optional) Name of ResourceGroup where Automation Account will be installed|FALSE|AzSKRG|Don't pass default value explicitly for this param| +|AutomationAccountName|(Optional) Name of AutomationAccount|FALSE|AzSKContinuousAssurance|Don't pass default value explicitly for this param| +|ResourceGroupNames|Comma-separated list of resource group names which cover the application resources that need to be scanned. |TRUE|None|Use **"*"** to cover all resource groups in the subscription.| +|LAWSId|Workspace ID of Log Analytics workspace which is used to monitor security scan results|TRUE|None|| +|LAWSSharedKey|Shared key of Log Analytics workspace which is used to monitor security scan results|TRUE|None|| +|AltLAWSId|(Optional) Workspace ID of alternate Log Analytics workspace to monitor security scan results|FALSE|None|| +|AltLAWSSharedKey|(Optional) Shared key of alternate Log Analytics workspace which is used to monitor security scan results|FALSE|None|| |WebhookUrl|(Optional) All the scan results shall be posted to this configured webhook |FALSE|None|| |WebhookAuthZHeaderName|(Optional) Name of the AuthZ header (typically 'Authorization')|FALSE|None|| -|WebhookAuthZHeaderValue|(Optional) Value of the AuthZ heade |FALSE|None|| +|WebhookAuthZHeaderValue|(Optional) Value of the AuthZ header |FALSE|None|| |ScanIntervalInHours|(Optional) Overrides the default scan interval (24hrs) with the custom provided value |FALSE|None|| |AzureADAppName|(Optional) Name for the Azure Active Directory(AD) Application that will be created in the subscription for running the runbooks. |FALSE|None|| +|ScanOnDeployment|(Optional) CA scan can be auto-triggered upon resource deployment.Installing CA with this flag will make sure that the Resource Group in which resource is deployed will be scanned. |FALSE|None|| +|UsageTelemetryLevel|(Optional) CA scan evets get captured at AzSK side using anonymous telemetry.Installing CA with this flag with value as None will disable scan telemetry being captured at AzSk side. |FALSE|Anonymous|| -**More about the 'AzureAdAppName' parameter:** +> NOTE: +> You can use **"*"** to cover all resource groups in the subscription. If **"*"** is specified, CA will automatically cover new resource groups that are added. Thus **"*"** might be a preferred option in enterprise-wide compliance/visibility initiatives based on CA. + +**More about the 'AzureADAppName' parameter:** The AzureADAppName parameter is optional. This represents the runtime account that will be used by the CA runbook to scan the subscription/resources. @@ -106,18 +150,19 @@ name and attempt to use it (in this case the user must have 'Owner' permission o Here's a quick summary of the permissions required for the user who sets up CA: - "Owner" access on the subscription -- Ability to create an AAD app in the tenant (this app is used as the runtime account for scanning via the CA runbook) -- "Owner" acceess to the AAD app if the user specifies one (or CA internally finds a previously created one) +- Ability to create an AAD app in the tenant (This permissions is only required if app does not exist in tenant) +- "Owner" access to the AAD app if the user specifies one (or CA internally finds a previously created one) **Note-1**: Completion of this one-time setup activity can take up to 2 hours. (This is because one of the things that setup does is download and add PowerShell modules for Azure PS library and for AzSK. This is a slow and sometimes flaky process and, as a result, the setup internally retries failed downloads. The Azure Automation product team is aware of this challenge and are working on a resolution.) - -**Note-2**: Due to the complexity of various dependent activities involved, there are multiple places where CA setup can get tripped up. +**Note-2**: Due to the complexity of various dependent activities involved, there are multiple places where CA setup can run into issues. It is important to verify that everything has worked without hiccups. Please review and ascertain each of the "Verifying" steps below carefully. +**Note-3**: If the person who had set up CA leaves organization/team then it's strongly advised to remove the service principal (configured in runtime account) access from subscription/AzSKRG to prevent any misuse. + **Step-2: Verifying that CA Setup is complete** **1:** In the Azure portal, select the application subscription that was used above and search for resources of type Automation Account. You should see an Automation Account created by the name 'AzSKContinuousAssurance'. Clicking on it will display the contents of the Automation Account (something that looks like the below, the counts shown may vary a little): @@ -142,37 +187,36 @@ It is important to verify that everything has worked without hiccups. Please rev ![04_CA_Downloaded_Modules](../Images/04_CA_Downloaded_Modules.PNG) -**Step-4: Verifying CA Runbook execution and OMS connectivity** +**Step-4: Verifying CA Runbook execution and Log Analytics connectivity** Once CA setup and modules download are completed successfully, the runbooks will automatically execute periodically (once a day) and scan the subscription and the specified resource groups for the application(s) for security issues. The outcomes of these scans will get stored in a storage account created by the installation (format : azsk\ e.g. azsk20170505181008) and follows a similar structure as followed by standalone SVT execution (CSV file, LOG file, etc.). -The results of the control evaluation are also routed to the OMS repository for viewing via a security dashboard. +The results of the control evaluation are also routed to the Log Analytics for viewing via a security dashboard. -Let us verify that the runbook output is generated as expected and that the OMS connectivity is setup and working correctly. +Let us verify that the runbook output is generated as expected and that the Log Analytics connectivity is setup and working correctly. **1:** Verify that CSV file and LOG file are getting generated as expected. 1. Go to Storage Explorer and look for a storage account with a name in azsk format in your subscription in 'AzSKRG' resource group. -2. Find a container called 'azskexecutionlogs' in this storage account. +2. Find a blob container called 'ca-scan-logs' in this storage account. 3. There should be a ZIP file named using a timestamp based on the date time for the manual execution in this container (most likely the ZIP file with the most recent creation date). 4. Download the ZIP file and extract its contents locally. The folder structure will be similar to how SVTs/Subscription Health scan generate when run locally. 5. In a single zip file you will find two folders (name format: Timestamp). One folder contains reports of Subscription Health scan and another folder contains reports of application(s) resource groups security scan. ![04_CA_Storage_Container](../Images/04_CA_Storage_Container.PNG) -**2:** Verify that data is being sent to the target OMS workspace +**2:** Verify that data is being sent to the target Log Analytics workspace -1. Go to the OMS dashboard that we used to setup CA above. -2. In the 'Search' window, enter Type=AzSK_CL Source_s=CC. Source will be changed to 'CA' in future. +1. Go to the Log Analytics workspace that we used to setup CA above. +2. Navigate to 'Logs' window, and enter Type=AzSK_CL Source_s=CA. (Source_s used to be 'CC' in the past.) 3. You should see results similar to the below: - ![04_CA_OMS](../Images/04_CA_OMS.PNG) + ![04_CA_Log_Analytics](../Images/04_CA_Log_Analytics.png) -Once CA is setup in the subscription, an app team can start leveraging the OMS Solution from AzSK as a one-stop dashboard -for visibility of security state. Please follow the steps in the OMS solution setup (in Alerting & Monitoring sub-section of -this notebook) to enable that part. +Once CA is setup in the subscription, an app team can start leveraging the Monitoring Solution from AzSK as a one-stop dashboard +for visibility of security state. Please follow the steps to setup the Monitoring solution [here](../05-Alerting-and-Monitoring#setting-up-the-azsk-monitoring-solution-step-by-step) to enable that part. [Back to top…](Readme.md#contents) -### Continuous Assurance - how it works (under the covers) +## Continuous Assurance - how it works (under the covers) The CA feature is about tracking configuration drift. This is achieved by enabling support for running AzSK SVTs/SS-Health via automation runbook. @@ -186,8 +230,8 @@ To host all the Continuous Assurance artifacts - Runbook (Name : Continuous_Assurance_Runbook) - To download/update Azure/AzSK modules and scan subscription/app resource groups - Variables - AppResourceGroupNames - - OMSWorkspaceId - - OMSSharedKey + - LAWSId + - LAWSSharedKey - ReportLogsStorageAccountName - Azure Run As Account - To authenticate runbook at runtime This account uses below certificate and connection. @@ -198,62 +242,70 @@ To host all the Continuous Assurance artifacts - CA_Helper_Schedule - This is a temporary schedule created by runbook to retry download of modules - Modules - Downloaded by the runbook -About 63 assets are created overall. #### Next Steps -Once CA is setup in the subscription, an app team can start leveraging the OMS Solution from AzSK as a one-stop dashboard for visibility of security state. +Once CA is setup in the subscription, an app team can start leveraging the Monitoring Solution from AzSK as a one-stop dashboard for visibility of security state. Occasionally, you may also feel the need to tweak the configuration of CA. See the "Update" section below about how to do that. [Back to top…](Readme.md#contents) -### Update existing Continuous Assurance Automation Account + +## Updating an existing Continuous Assurance setup + The '**Update-AzSKContinuousAssurance**' command can be used to make changes to a previously setup CA configuration. For instance, you may use it to: - update the target resource groups to include in the scanning -- switch the OMS workspace information that CA should use to send control evaluation events to +- switch the Log Analytics workspace information that CA should use to send control evaluation events to - use a different AAD SPN for the runbooks +- remove previously set LogAnalytics, AltLogAnalytics, Webhook settings or ScanOnDeployment mode for CA account. - etc. To do any or all of these: -1. Open the PowerShell ISE and login to your Azure account (using **Login-AzureRmAccount**). +1. Open the PowerShell ISE and login to your Azure account (using **Connect-AzAccount**). 2. Run the '**Update-AzSKContinuousAssurance**' command with required parameters given in below table. ```PowerShell Update-AzSKContinuousAssurance -SubscriptionId ` [-ResourceGroupNames ] ` - [-OMSWorkspaceId ] ` - [-OMSSharedKey ] ` - [-AltOMSWorkspaceId ] ` - [-AltOMSSharedKey ] ` + [-LAWSId ] ` + [-LAWSSharedKey ] ` + [-AltLAWSId ] ` + [-AltLAWSSharedKey ] ` [-WebhookUrl ] ` [-WebhookAuthZHeaderName ] ` [-WebhookAuthZHeaderValue ] ` [-ScanIntervalInHours ] ` [-AzureADAppName ] ` [-FixRuntimeAccount] ` + [-NewRuntimeAccount] ` [-FixModules] ` - [-RenewCertificate] + [-RenewCertificate]` + [-Remove
  • Runtime account deleted
    (Permissions required: Subscription owner)
  • Runtime account permissions missing
    (Permissions required: Subscription owner and AD App owner)
  • Certificate deleted/expired
    (Permissions required: Subscription owner and AD App owner)
  • |FALSE|None|| -|FixModules|Use this switch in case 'AzureRm.Automation' module extraction fails in CA Automation Account.|FALSE|None|| +|NewRuntimeAccount|Use this switch to setup new runtime account and the person running the command will become new SPN owner.This feature is helpful in case when CA certificate is expired but the SPN owner who had setup CA is not available and certificate can't be renewed. |FALSE|None|| +|FixModules|Use this switch in case Az.Automation/Az.Accounts module(s) extraction fails in CA Automation Account.|FALSE|None|| |RenewCertificate|Renews certificate credential of CA SPN if the caller is Owner of the AAD Application (SPN). If the caller is not Owner, a new application is created with a corresponding SPN and a certificate owned by the caller. CA uses the updated credential going forward.|FALSE|None|| +|ScanOnDeployment|CA scan can be auto-triggered upon resource deployment.Updating CA with this flag will make sure that the Resource Group in which resource is deployed will be scanned.|FALSE|None|| +|Remove|Use this switch to clear previously set LogAnalytics, AltLogAnalytics,Webhook settings from CA Automation Account or to unregister from scan on deployment mode|False|None|| +|UsageTelemetryLevel|Use this switch to stop anonymous telemetry capture at AzSK side.|False|Anonymous|| [Back to top…](Readme.md#contents) -### Remove Continuous Assurance Automation Account -1. Open the PowerShell ISE and login to your Azure account (using **Login-AzureRmAccount**). +## Removing a Continuous Assurance setup +1. Open the PowerShell ISE and login to your Azure account (using **Connect-AzAccount**). 2. Run the '**Remove-AzSKContinuousAssurance**' command as below. ```PowerShell @@ -265,8 +317,8 @@ Remove-AzSKContinuousAssurance -SubscriptionId [-DeleteStorage |DeleteStorageReports |Add this switch to delete AzSK execution reports from storage account. This will delete the storage container where reports are stored. Generally you will not want to use this option as all previous scan reports will be purged. |False |None|| [Back to top…](Readme.md#contents) -### Fetch details of an existing Continuous Assurance Automation Account -1. Open the PowerShell ISE and login to your Azure account (using **Login-AzureRmAccount**). +## Getting details about a Continuous Assurance setup +1. Open the PowerShell ISE and login to your Azure account (using **Connect-AzAccount**). 2. Run the '**Get-AzSKContinuousAssurance**' command as below. 3. Result will display the current status of CA in your subscription. If CA is not working as expected, it will display remediation steps else it will display a message indicating CA is in healthy state. 4. Once you follow the remediation steps, run the command again to check if anything is still missing in CA setup. Follow the remediation steps accordingly until the CA state becomes healthy. @@ -277,98 +329,250 @@ Get-AzSKContinuousAssurance -SubscriptionId [Back to top…](Readme.md#contents) -### Continuous Assurance through central scanning mode (Preview) - Step by Step +## Continuous Assurance (CA) - 'Central Scan' mode + +The description so far has focused on setting up CA in a single subscription. When you have multiple subscriptions, you can setup CA individually for scanning each subscription. Alternatively, you can also setup CA in what is called a 'central scan' mode. The 'central scan' mode is more suited for scenarios where a single central team wants to exercise oversight of several subscription using a single master subscription for scanning. This section describes this mode and how to set it up further. + + +Unlike the 'individual subscription' mode where each subscription get its own instance of CA automation account, runbook, scan logs etc., the 'central scan' mode uses a single 'master' subscription to perform all scanning activities from. Use the following steps to setup 'central scan' mode: -In scenarios where central team wants to monitor a group of subscriptions from a single and more controlled central subscription, this command would help to achieve such scenarios. #### Pre-requisites: -- The user executing this command should have "Owner" access on all the subscriptions that are being enabled for central scanning mode including the central subscription. -- User should have the latest version of the kit installed on the machine (>= v2.8.1) -- Optional: Have the own instance of AzSK setup for your org. This would provide more capabilities to control the scanning behavior +- The user executing this command should have "Owner" access on all the subscriptions that are being enabled for central scanning mode including the master subscription. +- User should have the latest version of the DevOps Kit installed on the machine (>= [AzSK v3.1.x](https://www.powershellgallery.com/packages/AzSK/3.1.0)) +- [Optional: Have a custom DevOps Kit policy setup for your org. This would provide more capabilities to control the scanning behavior. + (See [here](../07-Customizing-AzSK-for-your-Org/Readme.md) for more details on org policy.) + +### Central Scan mode - single versus multiple Automation accounts: +When setting up CA with central scan mode, you have a choice regarding division of the scanning workload between automation accounts. You can choose to have all target subscriptions scanned via a single automation account *or* you can configure multiple automation accounts to divide the scanning workload amongst them by assigning each automation account a subset of the subscriptions for scanning. These two options and when to choose which one are covered below: -#### Setup Continuous Assurance (CA) in central mode: -> **Note:** This feature is still in preview. +#### 1. Central Scan mode CA using a single Automation account (default behavior): -This can be achieved by adding extra params to the existing CA command. You can run the command below: +With this option, a single automation account will get created in the host (master) subscription, which will scan all the target subscriptions. This mode is suitable for scanning up to a max of 40-50 subscriptions. (As the number of target subscriptions increases, the frequency of scan for each subscription reduces. Ideally each subscription should get scanned at least once per day. The multiple Automation account option might help if the count of subscriptions to be scanned is higher.) + +##### 1.1 Setting up Continuous Assurance (CA) in Central Scan mode (single Automation account option): + +This can be achieved by adding extra params to the existing CA command as shown in the command below: ```PowerShell $SubscriptionId = '' -$ResourceGroupNames = '*' -$OMSWorkspaceId = '' -$OMSSharedKey = '' -$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. - -Install-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds -ResourceGroupNames $ResourceGroupNames -OMSWorkspaceId $OMSWorkspaceId -OMSSharedKey $OMSSharedKey -Preview +$ResourceGroupNames = '*' #This should always be '*' for Central Scan mode CA +$LAWSId = '' +$LAWSSharedKey = '' +$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. + +Install-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds + -ResourceGroupNames $ResourceGroupNames -LAWSId $LAWSId -LAWSSharedKey $LAWSSharedKey -CentralScanMode + [-LoggingOption ''] [-SkipTargetSubscriptionConfig] ```
    +The table below lists only the parameters that are mandatory or have specific needs when used in the central scan mode CA setup. For the overall set of parameters, please review the CA parameters table above. + |Param Name| Purpose| Required?| DefaultValue| Comments| |----------|--------|----------|-------------|---------| -|SubscritionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|SubscriptionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| |TargetSubscriptionIds| Comma separated list of subscriptionIds that needs to be scanned by the central subscription. Host subscription is always appended by default. No need to pass that value in this param| True | The user executing this command should be owner on these subscriptions. | |ResourceGroupNames| Comma separated list of ResourceGroupNames| True | Since you are planning to run in the central mode, you should use * as its value. This is because you need not have the same RG across all the subscriptions| -|OMSWorkspaceId| All the scanning events will be send to this OMSWorkspace. This will act as central monitoring dashboard | True | | -|OMSSharedKey| OMSSharedKey for the central monitoring dashboard| True | | -|AltOMSWorkspaceId|(Optional) Alternate Workspace ID of OMS to monitor security scan results|FALSE|None|| -|AltOMSSharedKey|(Optional) Shared key of Alternate OMS which is used to monitor security scan results|FALSE|None|| -|WebhookUrl|(Optional) All the scan results shall be posted to this configured webhook |FALSE|None|| -|WebhookAuthZHeaderName|(Optional) Name of the AuthZ header (typically 'Authorization')|FALSE|'Authorization'|| -|WebhookAuthZHeaderValue|(Optional) Value of the AuthZ heade |FALSE|24 hrs|| -|ScanIntervalInHours|(Optional) Overrides the default scan interval (24hrs) with the custom provided value |FALSE|None|| +|LAWSId| All the scanning events will be send to this Log Analytics workspace. This will act as central monitoring dashboard | True | | +|LAWSSharedKey| SharedKey for the central monitoring dashboard| True | | |LoggingOption| "IndividualSubs/CentralSub". This provides the capability to users to store the CA scan logs on central subscription or on individual subscriptions| False |CentralSub | -|Preview| It is mandatory to use preview switch| True | | +|SkipTargetSubscriptionConfig| (Optional) Use this switch if you dont have the owner permission on the target sub. This option assumes you have already done all the required configuration on the target sub. Check the note below| False| | +|CentralScanMode| Mandatory switch to specify in central scan mode| True | | +|UsageTelemetryLevel| Optional paramater to turn off anonymous telemetry at AzSK side if value set as None| False | Anonymous | + +
    + +> **Note:** If you are using switch -SkipTargetSubscriptionConfig, then it assumes you have done all the required configuration on the target subscriptions. +> Like, adding the CA SPN as Reader on target sub, Creating AzSK RG and a storage account name starting with azsk, Contributor permission to SPN on AzSKRG. +> If any of the steps are not done, then central scan automation account will skip those target subscriptions. +> You can use the script [here](https://github.com/azsk/DevOpsKit-docs/blob/master/04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md) to prepare one or more target subscriptions for central mode scanning. The example invocation at the bottom of the script shows how to invoke the function in the script for a single target sub. + +##### 1.2 Updating/modifying Central Scan mode CA (single Automation account option) -#### Append/modify/fix the central CA setup +In case you want to add subscriptions covered via central scanning mode you can use Update-AzSKContinuousAssurance as shown below. (All other CA configuration settings can also be updated as described in Update-AzSKContinuousAssurance earlier in this document.) + +```PowerShell +$SubscriptionId = '' +$LAWSId = '' +$LAWSSharedKey = '' +$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. + +Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds -CentralScanMode -FixRuntimeAccount + [-LoggingOption ] +``` +
    + +> **Note:** All other parameters as described in the main Update-AzSKContinuousAssurance parameters table apply. They are not repeated below for brevity. + +|Param Name| Purpose| Required?| DefaultValue| Comments| +|----------|--------|----------|-------------|---------| +|SubscriptionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|TargetSubscriptionIds| Comma separated list of subscriptionIds that needs to be scanned by the central subscription. It would always append the values provided in this param to the current scanning list.| True | The user executing this command should be owner on these subscriptions. | +|LoggingOption| "IndividualSubs/CentralSub" | False | Only provide if you want to change the logging option| +|FixRuntimeAccount| This will correct all the permissions issues related to the scanning account| False | Provide this switch only when you want to add new subscriptions for central scanning mode | +|CentralScanMode| It is mandatory to use CentralScanMode switch| True | | + +##### 1.3 Diagnosing the health of Central Mode CA (single Automation account option) + +You can run the command below to enquire the health of CA setup in your subscription. Note that the '-CentralScanMode' flag is not required for this command. + +```PowerShell +$SubscriptionId = '' + +Get-AzSKContinuousAssurance -SubscriptionId $SubscriptionId [-ExhaustiveCheck] +``` +
    + +|Param Name| Purpose| Required?| DefaultValue| Comments| +|----------|--------|----------|-------------|---------| +|SubscriptionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|ExhaustiveCheck| (Optional) By appending this switch it would check whether all the modules installed in central automation account are up to date| False | Only include if default diagnosis is not resulting in any issue | + +##### 1.4 Remove Central Scan mode CA from the master subscription (single Automation account option) In case you want to -
    (a) add new subscriptions to central scanning mode, or -
    (b) CA is not using the latest runbook, or -
    (c) OMS workspace needs to be updated, or -
    (d) OMS keys have been rotated and you want to use the latest keys, or -
    (e) AltOMS workspace details needs to updated, or -
    (f) Webhook details needs to updated, or -
    (g) ScanInterval needs to updated, or -
    (h) the scanning account credential needs to be rotated as part of hygiene/ expiry, or -
    (i) modify the logging option to central mode - -In all such scenarios, you can run the command below: +
    (a) unregister some subs from central scanning mode, or +
    (b) to delete the scan logs, or +
    (c) to remove the whole automation account + +```PowerShell +$SubscriptionId = '' + +Remove-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -DeleteStorageReports -CentralScanMode +``` + + +|Param Name| Purpose| Required?| DefaultValue| Comments| +|----------|--------|----------|-------------|---------| +|SubscriptionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|TargetSubscriptionIds| Comma separated list of target subIds which will be un-registered from the central scanning mode. | False | | +|DeleteStorageReports| Deletes all the scan logs from the azsk storage account based on the logging option and value provided in the target subscription. If used with out CentralScanMode switch, it would remove all logs from the host sub central storage account.| False | Only include if default diagnosis is not resulting in any issue | +|CentralScanMode| It is mandatory to use CentralScanMode switch| True | | + +>**Note** If just subscriptionId is passed, then it would check if the host sub is in central scanning mode, if so, user needs to pass CentralScanMode switch specifically. In these scenarios, it would remove the whole automation account from host sub. + + +#### 2. Central Scan mode CA using multiple Automation accounts + +If you are trying to scan multiple target subscriptions, then scanning all of them using a single Automation account can be tedious and face scale/performance issues. Furthermore, with too many subscriptions to scan, you may not be able to scan each subscription with the desired scan interval. +In such scenarios, you can use the multiple accounts approach by grouping your subscriptions into batches and scanning these batches +using multiple independent automation accounts with in the same host/central subscription. +In this scenario, all your logs, scanning configuration, attestation data is persisted under the default AzSKRG whereas each automation account will have its own dedicated RG for CA bookkeeping. + + +##### 2.1 Setting up Continuous Assurance (CA) in Central Scan mode (multiple Automation accounts option): + +When you have more than about 40-50 subscriptions to scan, it is better to use multiple Automation accounts option of the Central Scan mode. You need to split the overall set of target subscriptions into multiple groups and then decide names to use for the Automation account and the resource groups that will host the CA for each group. Once this grouping and naming is done, you simply run the central scan mode CA setup command once for each group (with additional parameters identifying the Automation account name and the resource group that will serve as the host for scanning the respective group). + +> **Note:** When using multi-Automation Account mode, be sure to provide a _unique_ Automation account name and a _unique_ resource group name for each CA setup. Basically, each such tuple represents a unique CA setup within the master/central subscription. You will need to carefully provide this tuple for subsequent Update-CA/Remove-CA calls as well...as it is this tuple that helps CA identify the subscription group being targeted. + +> Furthermore, make sure you do not use the default CA account name ("AzSKContinuousAssurance") or the default AzSK resource group name for the org (e.g., "AzSKRG") when using this mode. Those are reserved for the single CA account mode! + +```PowerShell +$SubscriptionId = '' +$ResourceGroupNames = '*' #This should always be '*' for Central Scan mode CA +$LAWSId = '' +$LAWSSharedKey = '' +$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. + +#if you have text file containing subscription ids then run below script +#$FileContent = Get-Content -Path "" +#$TargetSubscriptionIds = ($FileContent| foreach {$_.Trim()}) -join "," + +#if you have PowerShell array object containing subscription ids e.g. $SubIdArray = @("subid1","subid2","subid3") then run below script +#$TargetSubscriptionIds = ($SubIdArray| foreach {$_.Trim()}) -join "," + +$AutomationAccountLocation = '' +$AutomationAccountRGName = '' # e.g. AzSK-Category-ScanRG01 +$AutomationAccountName = '' # e.g. AzSKScanningAccount01 + +# **Note** You should use the unique names for AutomationAccountRG and AutomationAccountName to avoid any conflicts while setup + +Install-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds + -ResourceGroupNames $ResourceGroupNames -LAWSId $LAWSId -LAWSSharedKey $LAWSSharedKey + -AutomationAccountRGName $AutomationAccountRGName -AutomationAccountName $AutomationAccountName -AutomationAccountLocation $AutomationAccountLocation -CentralScanMode + [-LoggingOption ''] [-SkipTargetSubscriptionConfig] +``` +
    + +|Param Name| Purpose| Required?| DefaultValue| Comments| +|----------|--------|----------|-------------|---------| +|SubscriptionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|TargetSubscriptionIds| Comma separated list of subscriptionIds that needs to be scanned by the central subscription. Host subscription is always appended by default. No need to pass that value in this param| True | The user executing this command should be owner on these subscriptions. | +|ResourceGroupNames| Comma separated list of ResourceGroupNames| True | Since you are planning to run in the central mode, you should use * as its value. This is because you need not have the same RG across all the subscriptions| +|LAWSId| All the scanning events will be send to this Log Analytics workspace. This will act as central monitoring dashboard | True | | +|LAWSSharedKey| SharedKey for the central monitoring dashboard| True | | +|AutomationAccountLocation| (Optional) Location where the AutomationAccount to be created | False | | +|AutomationAccountRGName| Name of ResourceGroup which will hold the scanning automation account. Should be different than "AzSKRG". | True | e.g. AzSK-Category-ScanRG01 | +|AutomationAccountName| Name of the automation account which will scan the target subscriptions. (This should be different than "AzSKContinuousAssurance".) | True | e.g. AzSKScanningAccount01| +|LoggingOption| "IndividualSubs/CentralSub". This provides the capability to users to store the CA scan logs on central subscription or on individual subscriptions| False |CentralSub | +|SkipTargetSubscriptionConfig| (Optional) Use this switch if you dont have the owner permission on the target sub. This option assumes you have already one all the required configuration on the target sub. Check the note below| False| | +|CentralScanMode| Mandatory switch to specify in central scan mode| True | | + +
    + +> **Note:** If you are using switch -SkipTargetSubscriptionConfig, then it assumes you have done all the required configuration on the target subscriptions. +> Like, adding the CA SPN as Reader on target sub, Creating AzSK RG and a storage account name starting with azsk, Contributor permission to SPN on AzSKRG. +> If any of the steps are not done, then central scan automation account will skip those target subscriptions. +> You can use the script [here](https://github.com/azsk/DevOpsKit-docs/blob/master/04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md) to prepare one or more target subscriptions for central mode scanning. The example invocation at the bottom of the script shows how to invoke the function in the script for a single target sub. + +##### 2.2 Updating/modifying Central Scan mode CA (multiple Automation accounts option) + +In case you want to add/update new subscriptions to any of the groups, you can do so using the command below (this is similar to the single Automation account command, except that you have to specify the AutomationAccountRGName and AutomationAccountName): ```PowerShell $SubscriptionId = '' -$OMSWorkspaceId = '' -$OMSSharedKey = '' -$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. +$AutomationAccountRGName = '' # e.g. AzSK-Category-ScanRG01 +$AutomationAccountName = '' # e.g. AzSKScanningAccount01 +$TargetSubscriptionIds = '' #Need to provide comma separated list of all subscriptionId that needs to be scanned. -Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds -OMSWorkspaceId $OMSWorkspaceId -OMSSharedKey $OMSSharedKey -FixRuntimeAccount -LoggingOption CentralSub -Preview +#if you have text file containing subscription ids then run below script +#$FileContent = Get-Content -Path "" +#$TargetSubscriptionIds = ($FileContent| foreach {$_.Trim()}) -join "," + +#if you have PowerShell array object containing subscription ids e.g. $SubIdArray = @("subid1","subid2","subid3") then run below script +#$TargetSubscriptionIds = ($SubIdArray| foreach {$_.Trim()}) -join "," + +Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -TargetSubscriptionIds $TargetSubscriptionIds + -AutomationAccountRGName $AutomationAccountRGName -AutomationAccountName $AutomationAccountName -CentralScanMode -FixRuntimeAccount + [-LoggingOption ] ```
    +> **Note:** All other parameters as described in the main Update-AzSKContinuousAssurance parameters table apply. They are not repeated below for brevity. + |Param Name| Purpose| Required?| DefaultValue| Comments| |----------|--------|----------|-------------|---------| -|SubscritionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|SubscriptionId| Central subscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| |TargetSubscriptionIds| Comma separated list of subscriptionIds that needs to be scanned by the central subscription. It would always append the values provided in this param to the current scanning list.| True | The user executing this command should be owner on these subscriptions. | -|OMSWorkspaceId| All the scanning events will be send to this OMSWorkspace. This will act as central monitoring dashboard | False | Only provide if you want to change the workspace details | -|OMSSharedKey| OMSSharedKey for the central monitoring dashbaord| False | Only provide if you want to update the OMS Sharedkey along with workspaceId param | +|AutomationAccountRGName| Name of Resource Group which will hold the scanning automation account | True | e.g. AzSK-Category-ScanRG01 | +|AutomationAccountName| Name of the Automation Account which will scan target subscriptions | True | e.g. AzSKScanningAccount01| |LoggingOption| "IndividualSubs/CentralSub" | False | Only provide if you want to change the logging option| |FixRuntimeAccount| This will correct all the permissions issues related to the scanning account| False | Provide this switch only when you want to add new subscriptions for central scanning mode or if scanning account credential needs to be updated | -|Preview| It is mandatory to use preview switch| True | | +|CentralScanMode| It is mandatory to use CentralScanMode switch| True | | -#### Diagnose the health of central CA +##### 2.3 Diagnosing the health of Central Mode CA (multiple Automation accounts option) -You could run the command below. It would diagnose the Continuous Assurance Automation account running under central subscription +You can run the command below to enquire the health of CA setup in your subscription. In the case of multi-Automation account setup, you can query the status of one setup at a time. As a result, you must pass the name of the automation account and the automation account resource group as parameters. Note that the '-CentralScanMode' flag is not required for this command. ```PowerShell $SubscriptionId = '' +$AutomationAccountRGName = '' # e.g. AzSK-Category-ScanRG01 +$AutomationAccountName = ' # e.g. AzSKScanningAccount01 -Get-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -ExhaustiveCheck +Get-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -AutomationAccountRGName $AutomationAccountRGName -AutomationAccountName $AutomationAccountName [-ExhaustiveCheck] ```
    |Param Name| Purpose| Required?| DefaultValue| Comments| |----------|--------|----------|-------------|---------| -|SubscritionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| -|ExhaustiveCheck| By appending this switch it would check whether all the modules installed in central automation account are up to date| False | Only include if default diagnosis is not resulting in any issue | +|SubscriptionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions +|AutomationAccountRGName| Name of Resource Group which will hold the scanning automation account | True | e.g. AzSK-Category-ScanRG01 | +|AutomationAccountName| Name of the Automation Account which will scan target subscriptions | True | e.g. AzSKScanningAccount01| +|ExhaustiveCheck| (Optional) By appending this switch it would check whether all the modules installed in central automation account are up to date| False | Only include if default diagnosis is not resulting in any issue | + -#### Remove CA from the central subscription +##### 2.4 Remove Central Scan mode CA from the master subscription (multiple Automation accounts option) In case you want to
    (a) unregister some subs from central scanning mode, or @@ -377,47 +581,116 @@ In case you want to ```PowerShell $SubscriptionId = '' +$AutomationAccountRGName = '' # e.g. AzSK-Category-ScanRG01 +$AutomationAccountName = ' # e.g. AzSKScanningAccount01 -Remove-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -DeleteStorageReports -Preview +Remove-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -DeleteStorageReports -AutomationAccountRGName $AutomationAccountRGName -AutomationAccountName $AutomationAccountName -CentralScanMode ``` |Param Name| Purpose| Required?| DefaultValue| Comments| |----------|--------|----------|-------------|---------| -|SubscritionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| +|SubscriptionId| Central SubscriptionId which is responsible for scanning all the other subscriptions| True | This subscription would host the Automation account which is responsible for scanning all the other subscriptions| |TargetSubscriptionIds| Comma separated list of target subIds which will be un-registered from the central scanning mode. | False | | -|DeleteStorageReports| Deletes all the scan logs from the azsk storage account based on the logging option and value provided in the target subscription. If used with out preview switch, it would remove all logs from the host sub central storage account.| False | Only include if default diagnosis is not resulting in any issue | +|AutomationAccountRGName| Name of Resource Group which will hold the scanning automation account | True | e.g. AzSK-Category-ScanRG01 | +|AutomationAccountName| Name of the Automation Account which will scan target subscriptions | True | e.g. AzSKScanningAccount01| +|DeleteStorageReports| Deletes all the scan logs from the azsk storage account based on the logging option and value provided in the target subscription. If used with out CentralScanMode switch, it would remove all logs from the host sub central storage account.| False | Only include if default diagnosis is not resulting in any issue | +|CentralScanMode| It is mandatory to use CentralScanMode switch| True | | ->**Note** If just subscrptionId is passed, then it would check if the host sub is in central scanning mode, if so, user needs to pass Preview switch. In these scenarios, it would remove the whole automation account from host sub. +>**Note** If just subscriptionId is passed, then it would check if the host sub is in central scanning mode, if so, user needs to pass CentralScanMode switch. In these scenarios, it would remove the whole automation account from host sub. [Back to top…](Readme.md#contents) +## Scan Databricks using custom AzSK Job +The basic idea behind setting up job in databricks workspace is to continuously validate security state of workspace. We are also exploring this as a general approach to expand AzSK scans into the ‘data’ plane for various cluster technologies. + +>**Note:** This feature is currently in preview, changes are expected in upcoming releases. + +### Setting up Job - Step by Step + +In this section, we will walk through the steps of setting up a AzSK Job in databricks workspace. + +To get started, we need the following: +1. The user setting up Job needs to have 'admin' access to the Databricks workspace. + +2. User should have generated a Personal Access Token(PAT). + +**Step-1: Setup** + +0. Copy latest script from scripts section(SetupDatabricksScanJob.md). +1. Open the PowerShell ISE and paste script. +2. Run the script after updating required parameters. +3. When prompted enter personal access token(PAT). + +**Step-2: Verifying that Job Setup is complete** + +**1:** Go to your Databricks workspace that was used above. In workspace you should see an folder created by the name 'AzSK'. Inside this folder, there should be a notebook by the name "AzSK_CA_Scan_Notebook". + +**2:** Go to jobs in your workspace, there should be a job by the name "AzSK_CA_Scan_Job". + +>**Note:** To ensure the proper access control of Notebook and Job, you should use Workspace Access Control and Job Access Control to prevent unauthorized access to notebook contents and job. + +### How it works (under the covers) + +The Job installation script that sets up Job creates the following resources in your workspace: + +- Secret scope (Name : AzSK_CA_Secret_Scope) :- +To keep personal access token(PAT) that will be used further by Notebook to scan controls. +- Folder (Name : AzSK) :- To store the scan Notebook. +- Notebook (Name : AzSK_CA_Scan_Notebook) :- This is the notebook that will contain logic to run AzSK control scan over workspace. +- Job (Name : AzSK_CA_Scan_Job) :- This is the job that will be used to run Notebook on a scheduled basis. + ### FAQ #### What permission do I need to setup CA? You need to be 'Owner' on the subscription. This is required because, during CA setup, we add RBAC access to an Azure AD App (SPN) that's utilized for running the 'security scan' runbooks in Azure Automation. Only an'Owner' for a subscription has the right to change subscription RBAC. -#### Is it possible to setup CA if there is no OMS workspace? -No. The intent of CA is to scan regularly and be able to monitor the outcomes for security drift. Out of the box, AzSK CA uses OMS for the monitoring capabilities. (Basically, AzSK sends control evaluation results to a connected OMS workspace.) +#### SPN permission could not be set while renewing the CA certificate. What should I do? +In order to fix missing permissions/ setup new runtime account, you need to be an ‘Owner’ on the subscription. This is required because we add RBAC access to an Azure AD App (SPN) that's utilized for running the 'security scan' runbooks in Azure Automation. Only an 'Owner' for a subscription has the right to change subscription RBAC. Please verify whether you have ‘Owner’ permission on the subscription. + +#### What are AzSKRG and AzSK_CA_SPN used for? + +The AzSK Continuous Assurance (CA) setup basically provisions your subscription with the ability to do daily scans and sends the scan results to your Log Analytics workspace. +To do the scanning, the CA setup process creates a runtime account (owned by you) and grants that account 'Reader' access to your subscription. This is the AzSK_CA_SPN_xxxx that you will notice in a 'Reader' role if you look at the Access Control (IAM) list for your subscription. + +The CA setup also creates an automation account that holds the runbook (scanning code), the schedules (that trigger the daily scan) and other configuration parameters (e.g., your Log Analytics workspace info, target resource groups list, etc.) This, and other artifacts related to AzSK and functioning of AzSK commands, are held in a resource group called 'AzSKRG' in your subscription. + +Each day, the runbook executes under the identity of the AzSK_CA_SPN_xxxx runtime account and performs a scan of the subscription and contained resources (per the currently applicable baseline controls list). + +At the end of the each scan, the SPN needs some place to store the results (so that they can be examined by someone as need be later). For the purpose of storing the ZIP files from daily scans, a storage account is used. This storage account is also held within the same (AzSKRG) resource group and a blob container called 'AzSKexecutionlogs' is where the ZIP files are written each day. Because the CA SPN writes to the storage account, it needs 'Contributor' access to the 'AzSKRG' resource group. This access is also setup during the Install-AzSKContinuousAssurance (CA setup) command. -#### Which OMS workspace should I use for my team when setting up CA? +In general, all artifacts within the AzSKRG resource group are considered 'read only'. Respective AzSK cmdlets have the logic to manage these resources built-in. You should not make any modifications directly to either the contents of this resource group or to the permissions of the SPN (AzSK_CA_SPN_xxxx) as this may impact the functioning of AzSK CA or other AzSK commands. + +#### How to fix SPN permissions for my AzSK Continuous Assurance setup? + +The AzSK_CA_SPN is used to perform scanning and do the bookkeeping necessary for Continuous Assurance scans. As a result, during CA installation, it is granted 'Reader' access at subscription scope and 'Contributor' access at AzSKRG resource group scope. If any of these are changed/removed, CA functioning will be impacted. To revert to correct permissions run the following: + +```PowerShell +Update-AzSKContinuousAssurance -SubscriptionId -FixRuntimeAccount +``` +See the above question for more info about the SPN and AzSKRG. + +#### Is it possible to setup CA if there is no Log Analytics workspace? +No. The intent of CA is to scan regularly and be able to monitor the outcomes for security drift. Out of the box, AzSK CA uses Log Analytics for the monitoring capabilities. (Basically, AzSK sends control evaluation results to a connected Log Analytics workspace.) + +#### Which Log Analytics workspace should I use for my team when setting up CA? Check with your service offering leader/org's cloud lead. You would typically use one of the following options: - Utilize a workspace is shared across a related set of services from your SO -- Create a new OMS workspace and use that exclusively for your service ('free' tier is OK for just AzSK use cases) +- Create a new Log Analytics workspace and use that exclusively for your service ('free' tier is OK for just AzSK use cases) - Utilize an IT-wide shared workspace #### Why does CA setup ask for resource groups? CA supports scanning a subscription and a set of cloud resources that make up an application. These cloud resources are assumed to be hosted within one or more resource groups. A typical CA installation takes both the subscription info and resource groups info. #### How can I find out if CA was previously setup in my subscription? -You can check using the "Get-AzSKContinuousAssurance" cmdlet. If CA is correctly setup, it will show a list of artifacts that are deployed during CA setup (e.g., Automation Account, Connections, Schedules, OMS workspace info, etc.). If CA has not been setup, you will see a message indicating so. +You can check using the "Get-AzSKContinuousAssurance" cmdlet. If CA is correctly setup, it will show a list of artifacts that are deployed during CA setup (e.g., Automation account, Connections, Schedules, Log Analytics workspace info, etc.). If CA has not been setup, you will see a message indicating so. #### How can I tell that my CA setup has worked correctly? There are 2 important things you should do to verify this: Run the Get-AzSKContinuousAssurance and confirm that the output tells you as in the previous question. -Verify that the runbooks have actually started scanning your subscription and resource groups. You can check for this in OMS. +Verify that the runbooks have actually started scanning your subscription and resource groups. You can check for this in Log Analytics. #### Is providing resource groups mandatory? We would like teams to, at a minimum, provide the list of resource groups that cover the most critical components of their application. It is unlikely that you will just have a subscription but no important resources inside it. Still, if you absolutely can't provide a resource group, then specify the "*"* as the resource group when setting up CA. @@ -426,19 +699,112 @@ If you do provide **"*"** as an option, CA will automatically grow/shrink the re #### What if I need to change the resource groups after a few weeks? That is easy! Just run the Update-AzSKContinuousAssurance cmdlet with the new list of resource groups you would like monitored. -#### Do I need to also setup AzSK OMS solution? +#### Do I need to also setup AzSK Monitoring solution? This part is not mandatory for CA itself to work. -However, setting up the AzSK OMS solution is recommended as it will help you get a richer view of continuous assurance for your subscription and resources as scanned by CA. Secondly, it will give you several out-of-box artefacts to assist with security monitoring for your service. For instance, you will start getting email alerts if any of the high or critical severity controls from AzSK fail in your service. +However, setting up the AzSK Monitoring solution is recommended as it will help you get a richer view of continuous assurance for your subscription and resources as scanned by CA. Secondly, it will give you several out-of-box artefacts to assist with security monitoring for your service. For instance, you will start getting email alerts if any of the high or critical severity controls from AzSK fail in your service. + +#### How to renew the certificate used for Continuous Assurance? + +#### Option 1: Renew certificate using powershell command + +The SPN used for daily scanning by AzSK CA uses a cert credential which has a default expiry of 6 months. When the cert comes close to expiry both the Azure portal and the Get-AzSKContinuousAssurance command warn about a need to renew the credential. Here's how to renew the cert: + +The SPN belongs to an AAD application that is created on behalf of the person who setup CA for the first time. You need to ensure that either that person performs the renewal or you can request that person to give you 'Owner' permission to that application. If the owner is unavailable (or has left the org) then you can create altogether new application in AAD (owned by you), SPN and a certificate credential and new SPN will be used for scanning your subscription moving forward. + +Run the following command to renew CA certificate. + +```PowerShell +Update-AzSKContinuousAssurance -SubscriptionId -RenewCertificate +``` +Run the following command to create new application in AAD (owned by you). + +```PowerShell +Update-AzSKContinuousAssurance -SubscriptionId -NewRuntimeAccount +``` + +Verify that it worked by running Get-AzSKContinuousAssurance again to confirm that the warning is gone. + +```PowerShell +Get-AzSKContinuousAssurance -SubscriptionId +``` + +Note: +If you don't know who ran CA setup earlier, you can find the owner of the AAD SPN by going to "Azure Active Directory" in the left pane in the portal and clicking "Enterprise Applications" and searching for the specific SPN (as shown below). Once you find the SPN, click on it and click "Owners". You can now contact one of the listed owners to either perform the above steps or add you as the owner so you can. + +#### Option 2: Renew certificate from Portal + +**Prerequisites:** +You need to be owner on the Subscription and SPN + +**Steps to renew certificate from portal:** -#### How much does it cost to setup Continuous Assurance alongwith OMS monitoring solution? +1) Go to AzSKRG Resoure Group (or the one which has your AzSK CA automation account). + +![01_RenewCertfromPortal](../Images/01_RenewCertfromPortal.png) + +2) Go to "Automation Account -> Run as accounts -> Azure Run as account".Click on "Renew certificate". + +![04_RenewCertfromPortal](../Images/04_RenewCertfromPortal.png) + +3) After clicking "Renew certificate" click on option "Yes" and then it will initiate the certificate renewal as displayed in below screenshots. + +![05_RenewCertfromPortal](../Images/05_RenewCertfromPortal.png) +![06_RenewCertfromPortal](../Images/06_RenewCertfromPortal.png) + +4) On successful renewal of certificate you will be able to see that the expiration date gets extended. + +![07_RenewCertfromPortal](../Images/07_RenewCertfromPortal.png) + +#### What are some example controls that are not scanned by CA? + +Here are a few examples of controls that CA cannot fully scan or can only 'partially' infer compliance for: +* Azure_Subscription_AuthZ_Dont_Use_NonAD_Identities - requires Graph API access to determine if an AAD object is an 'external' identity
    +* Azure_Subscription_AuthZ_Remove_Management_Certs - querying for management certs requires Co-Admin permission
    +* Azure_AppService_AuthN_Use_AAD_for_Client_AuthN - often this is implemented in code so an app owner has to attest this control. Also, any 'security-related' config info is not accessible to the 'Reader' RBAC role.
    +* Azure_CloudService_SI_Enable_AntiMalware - needs co-admin access.
    +* Azure_CloudService_AuthN_Use_AAD_for_Client_AuthN - no API available to check this (has to be manually attested).
    +* Azure_Storage_AuthN_Dont_Allow_Anonymous - needs 'data plane' access to storage account (CA SPN being a 'Reader' cannot do 'ListKeys' to access actual data).
    +As always, the most foolproof way to check all control failures is to ensure you are doing the following: + +Step-1: Update to the latest version of AzSK (it will tell you each time a command starts if your version is not the latest) + +Step-2: Run a subscription controls scan (as Co-Admin) with "-UseBaselineControls" flag + +Step-3: Run a complete scan of resources (as Co-Admin if you have classic resources or as Owner if you don't) + +Step-4: Lastly, if you fix or attest any controls which CA cannot scan, you may need to rerun (b) or (c) above at least once so that the final status of those non-CA controls gets sent to the Azure Monitor. + +#### Should I manually update modules in the AzSK CA automation account? + +No! Manually updating Azure modules like that will break AzSK CA. + +AzSK is reliant on a specific version of Az PowerShell modules. It is extensively tested against that version (and that version only). The Continuous Assurance setup process ensures that the correct version of Az modules is installed and imported into the CA automation account. If you attempt to update Azure modules (see pic below), it may bring in incompatible versions of Az modules and cause CA scanning to break. + +Note that once in a few months, the AzSK team reviews new releases of Az modules and updates the dependencies after extensive testing. At that point, the CA automation account will be automatically updated to import the newer modules. (No action is needed from your side.) + +If Azure modules happens to be updated other than AzSK dependancy version(One option is using "Update Azure Module" in Portal), you can recover module dependency by deleting AzSK module from automation account and triggering Runbook job. Runbook will install AzSK with all dependencies. + +**Note:** If you are using Org policy feature, make sure you have latest RunbookCoreSetup file present in policy store. Org Policy update [page](https://aka.ms/devopskit/orgpolicy/updates) gives instruction to update coresetup file against latest AzSK versions. + +#### Difference between scanned controls from CA v. ad hoc scans + +Some controls require elevated access and are not scanned by CA because the CA runtime account is only configured with 'Reader' privilege on the subscription. + +The elevated access required may itself be different based on the control... e.g., some classic/v1 controls (such as presence of management certs) can be checked only if the runtime account has 'Co-Admin' privilege. Other controls (such as RBAC access to non-AAD identities) can be checked if you have read access to the AAD Graph. Yet others may need 'data plane' access (e.g., is a storage blob set to be publicly accessible?). + +Such controls will be counted as 'failing' by default until you run the scans manually (which is when the actual result will start reflecting for them). + +Also, when running scans manually, make sure you are on the latest version of the kit. That may also cause a discrepancy between a CA scan and a local scan. (CA always runs using the latest version of the kit.) + +#### How much does it cost to setup Continuous Assurance along with the Monitoring solution? Using the following ballpark calculations (and service costs as of Q1-FY18), we estimate that a Continuous Assurance -setup along with an OMS workspace for monitoring will cost a little about $80/year for a typical +setup along with a Log Analytics workspace for monitoring will cost a little about $80/year for a typical subscription with about 30-40 resources of various types.   -The average cost of AzSK CA and AzSK OMS solution per Azure resources comes to about $2.7 per year. (So, assuming +The average cost of AzSK CA and AzSK Monitoring solution per Azure resources comes to about $2.7 per year. (So, assuming that a typical app has about 30 resources, we get about $81/year for an application.) -The main/dominant component of the cost is automation runtime (storage/OMS costs are negligible in comparison). +The main/dominant component of the cost is automation runtime (storage/Azure Monitor costs are negligible in comparison).   ###### Assumptions: @@ -472,9 +838,9 @@ The main/dominant component of the cost is automation runtime (storage/OMS costs - Total Blob Storage Cost (retention + listing + access) - 0.00 + 0.12 + 0.02 = $0.14/year   -###### (c) OMS storage cost: ($0.34/year) +###### (c) Log Analytics storage cost: ($0.34/year) -- Assumes that the team is using OMS for monitoring in general, otherwise, just for AzSK, free tier is sufficient. +- Assumes that the team is using Log Analytics for monitoring in general, otherwise, just for AzSK, free tier is sufficient. - Data Upload - Rate = $2.3 / GB / month - Our usage = 10KB / resource scan => 300KB added per day = ~10MB data written for the month  = (2.3*10*12/1000) = $0.27/year @@ -483,12 +849,54 @@ The main/dominant component of the cost is automation runtime (storage/OMS costs - Rate - $0.10 / GB / month - Our usage = 60MB avg/month (at mid-year)  = $0.10 * 0.06 *12 = $0.07/year -- Total OMS Cost (Upload + Retention)   +- Total Log Analytics Cost (Upload + Retention)   - 0.27+0.07 = $0.34/year +[Back to top…](Readme.md#contents) + +## Continuous Assurance (CA) - Trigger scan on resource deployment (Preview) + +When you want to trigger scan on resource deployment in a subscription, need to use the flag -ScanOnDeployment. Using this flag will make sure to add an alert which will trigger the newly added runbook and scan the resource group in which the resource(s) have been deployed.ScanOnDeployment currently is not supported for Multi CA and Central Scan mode CA. +ScanOnDeployment works for resource deployment operation only, doesn't work on resource deletion. + +#### 1. Install CA with flag -ScanOnDeployment + +This can be achieved by adding extra param to the existing CA command as shown in the command below: + +```PowerShell +$SubscriptionId = '' +$ResourceGroupNames = '*' #This should always be '*' +$LAWSId = '' +$LAWSSharedKey = '' + +Install-AzSKContinuousAssurance -SubscriptionId $SubscriptionId + -ResourceGroupNames $ResourceGroupNames -LAWSId $LAWSId -LAWSSharedKey $LAWSSharedKey -ScanOnDeployment +``` + +#### 2. Update CA with flag -ScanOnDeployment + +In case you want to add/edit subscriptions covered via scan on deployment mode you can use Update-AzSKContinuousAssurance as shown below. + +```PowerShell +$SubscriptionId = '' + +Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -ScanOnDeployment +``` + +#### 3. Remove flag -ScanOnDeployment + +In case you want to unregister sub from scan on deployment mode need to run command as below: + +```PowerShell +$SubscriptionId = '' + +Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId -Remove ScanOnDeployment +``` + + #### Troubleshooting -Please reach out to us at AzSDKSupExt@microsoft.com if you face any issues with this feature. +Please reach out to us at [azsksup@microsoft.com]() if you face any issues with this feature. [Back to top…](Readme.md#contents) diff --git a/04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md b/04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md new file mode 100644 index 00000000..98e40eb2 --- /dev/null +++ b/04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md @@ -0,0 +1,257 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +```PowerShell +function PrepareTargetSubscriptionForCentralModeCA($SubscriptionId, $Location, $AADAppName, $LoggingOption) +{ + #Do not change this rgName value unless you have your own AzSK org-specific policy setup + $rgName = 'AzSKRG' + + #region Step 1: Set context to target subscription + Write-Host "Changing current subscription context to [$subscriptionId]..." -ForegroundColor Yellow + Set-AzContext -Subscription $subscriptionId | Out-Null + Write-Host "Completed changing subscription context to [$subscriptionId]." -ForegroundColor Green + #endregion + + #region Step 2: Check if the AzSK resource group exists + $isRGPresent = (Get-AzResourceGroup -Name $rgName -ErrorAction SilentlyContinue | Measure-Object).Count -ne 0 + #endregion + + #region Step 3: Check whether Storage Resource provider is registered + + $providerNamespace = "Microsoft.Storage"; + Write-Host "Checking if resource provider [$providerNamespace] is registered..." -ForegroundColor Yellow + $isRegistered = (Get-AzResourceProvider -ProviderNamespace $providerNamespace | Where-Object { $_.RegistrationState -ne "Registered" } | Measure-Object).Count -eq 0 + #endregion + + + #region Step 4: Check whether AzSK storage account is present + $storageAccountPreName = 'azsk'; + $storageResourceType = "Microsoft.Storage/storageAccounts" + $storageType = 'Standard_LRS'; + $storageAccount = Get-AzResource -ResourceGroupName $rgName -Name "*$storageAccountPreName*" -ResourceType $storageResourceType -ErrorAction SilentlyContinue + $isStoragePresent = (($storageAccount | Where-Object{$_.Name -match '^azsk\d{14}$'} | Measure-Object).Count -ne 0) + #endregion + + #region Step 5: Grant required permissions on target sub and AzSK RG + $ADApplication = Get-AzADApplication -DisplayNameStartWith $AADAppName | Where-Object -Property DisplayName -eq $AADAppName + if(($ADApplication | Measure-Object).Count -le 0) + { + throw "AADApplication [$AADAppName] not found. You must specify an existing app name for which you are Owner." + } + + $haveRGAccess = $false; + $haveSubAccess = $false; + $spPermissions = Get-AzRoleAssignment -ServicePrincipalName $ADApplication.ApplicationId + #endregion + + + if($LoggingOption -eq "IndividualSub") + { + #region Step 2: Create the AzSK resource group + + #check if the resource group exists + Write-Host "Checking if resource group [$rgName] exists in the target subscription..." -ForegroundColor Yellow + if(-not $isRGPresent) + { + Write-Host "Creating new resource group [$rgName]..." -ForegroundColor Yellow + $newRG = New-AzResourceGroup -Name $rgName -Location $Location -ErrorAction Stop + } + $azSKRG = $null; + + #wait until resource group creation is completed + $retryCount = 6 + $localTimeout = $baseTimeout; + while($retryCount -gt 0 -and $null -eq $azSKRG) + { + $azSKRG = Get-AzResourceGroup -Name $rgName -ErrorAction SilentlyContinue; + if($null -eq $azSKRG) + { + Write-Host "Waiting...sleep interval: [$localTimeout] RetryCount: [$retryCount]" + Start-Sleep -Seconds $localTimeout + $localTimeout += 10 + $retryCount--; + } + } + Write-Host "Completed creating resource group [$rgName]" -ForegroundColor Green + #endregion + + #region Step 3: Register for Storage Resource provider + Write-Host "Checking if resource provider [$providerNamespace] is registered..." -ForegroundColor Yellow + + if($isRegistered) + { + Write-Host "Resource provider [$providerNamespace] is already registered" -ForegroundColor Green + } + + else + { + Register-AzResourceProvider -ProviderNamespace $providerNamespace + $retryCount = 10; + $localTimeout = $baseTimeout; + while($retryCount -ne 0 -and -not $isRegistered) + { + $isRegistered = ((Get-AzResourceProvider -ProviderNamespace $providerNamespace | Where-Object { $_.RegistrationState -ne "Registered" } | Measure-Object).Count -eq 0); + if(-not $isRegistered) + { + Write-Host "Waiting...Sleeping Interval: [$localTimeout] RetryCount: [$retryCount]" + Start-Sleep -Seconds $localTimeout + $retryCount--; + $localTimeout += 5 + } + } + Write-Host "Completed registering resource provider [$providerNamespace]" -ForegroundColor Green + } + #endregion + + #region Step 4: Create AzSK storage account + if(-not $isStoragePresent) + { + $storageAccountName = ($storageAccountPreName + (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss")); + $newStorage = New-AzStorageAccount -ResourceGroupName $rgName ` + -Name $storageAccountName ` + -SkuName $storageType ` + -Location $Location ` + -Kind BlobStorage ` + -AccessTier Cool ` + -EnableHttpsTrafficOnly $true ` + -ErrorAction Stop + + $retryAccount = 6 + $localTimeout = $baseTimeout; + while($null -eq $storageObject -and $retryAccount -gt 0) + { + $storageObject = Get-AzStorageAccount -ResourceGroupName 'AzSKRG' -Name $storageAccountName -ErrorAction SilentlyContinue + if($null -eq $storageObject) + { + Write-Host "Waiting...sleep interval: [$localTimeout] RetryCount: [$retryCount]" + Start-Sleep -seconds $localTimeout + $localTimeout += 5; + $retryAccount--; + } + } + + #the below settings are required to create compliant AzSK storage + if ($storageObject) { + $currentContext = $storageObject.Context + $logging= Set-AzStorageServiceLoggingProperty -ServiceType Blob -LoggingOperations All -Context $currentContext -RetentionDays 365 -PassThru -ErrorAction Stop + $metrics= Set-AzStorageServiceMetricsProperty -MetricsType Hour -ServiceType Blob -Context $currentContext -MetricsLevel ServiceAndApi -RetentionDays 365 -PassThru -ErrorAction Stop + } + Write-Host "Created a new AzSK storage account [$storageAccountName]" -ForegroundColor Green + } + else + { + Write-Host "AzSK storage account is already present" -ForegroundColor Green + } + #endregion + + #region Step 5: Grant required permissions on target sub and AzSK RG + Write-Host "Setting up permissions for AzSK CA SPN [$AADAppName]..." -ForegroundColor Yellow + if(($spPermissions|Measure-Object).count -gt 0) + { + $haveRGAccess = ($spPermissions | Where-Object {$_.scope -eq (Get-AzResourceGroup -Name $rgName).ResourceId -and $_.RoleDefinitionName -eq "Contributor" }|measure-object).count -gt 0 + $haveSubAccess = ($spPermissions | Where-Object {$_.scope -eq "/subscriptions/$subscriptionId" -and $_.RoleDefinitionName -eq "Reader"}|Measure-Object).count -gt 0 + } + + if(-not $haveRGAccess) + { + New-AzRoleAssignment -Scope $azSKRG.ResourceId -RoleDefinitionName Contributor -ServicePrincipalName $ADApplication.ApplicationId -ErrorAction SilentlyContinue | Out-Null + Write-Host "Completed granting access to AzSK CA SPN on ResourceGroup [$rgName]" -ForegroundColor Green + } + else + { + Write-Host "AzSK CA SPN already have required access on ResourceGroup [$rgName]" -ForegroundColor Green + } + if(-not $haveSubAccess) + { + New-AzRoleAssignment -RoleDefinitionName Reader -ServicePrincipalName $ADApplication.ApplicationId -ErrorAction SilentlyContinue | Out-Null + Write-Host "Completed granting access to AzSK CA SPN on Subscription" -ForegroundColor Green + } + else + { + Write-Host "AzSK CA SPN already have required access on Subscription" -ForegroundColor Green + } + #endregion + } + + elseif($LoggingOption -eq "CentralSub") + { + #region Step 2: Check if the AzSK resource group exists + + Write-Host "Checking if resource group [$rgName] exists in the target subscription..." -ForegroundColor Yellow + if($isRGPresent) + { + Write-Host "AzSK resource group is already present" -ForegroundColor Green + } + #endregion + + #region Step 3: Check whether Storage Resource provider is registered + + Write-Host "Checking if resource provider [$providerNamespace] is registered..." -ForegroundColor Yellow + if($isRegistered) + { + Write-Host "Storage Resource Provider is already registered" -ForegroundColor Green + } + #endregion + + + #region Step 4: Check whether AzSK storage account is present + Write-Host "Checking if AzSK storage account is present..." -ForegroundColor Yellow + #check if storage account is present + if($isStoragePresent) + { + Write-Host "AzSK storage account is already present" -ForegroundColor Green + } + #endregion + + #region Step 5: Grant required permissions on target sub and AzSK RG + Write-Host "Setting up permissions for AzSK CA SPN [$AADAppName]..." -ForegroundColor Yellow + if(($spPermissions|Measure-Object).count -gt 0) + { + if($isRGPresent -and $isRegistered -and $isStoragePresent) + { + $haveRGAccess = ($spPermissions | Where-Object {$_.scope -eq (Get-AzResourceGroup -Name $rgName).ResourceId -and $_.RoleDefinitionName -eq "Contributor" }|measure-object).count -gt 0 + if(-not $haveRGAccess) + { + New-AzRoleAssignment -Scope $azSKRG.ResourceId -RoleDefinitionName Contributor -ServicePrincipalName $ADApplication.ApplicationId -ErrorAction SilentlyContinue | Out-Null + Write-Host "Completed granting access to AzSK CA SPN on ResourceGroup [$rgName]" -ForegroundColor Green + } + else + { + Write-Host "AzSK CA SPN already have required access on ResourceGroup [$rgName]" -ForegroundColor Green + } + } + $haveSubAccess = ($spPermissions | Where-Object {$_.scope -eq "/subscriptions/$subscriptionId" -and $_.RoleDefinitionName -eq "Reader"}|Measure-Object).count -gt 0 + } + + if(-not $haveSubAccess) + { + New-AzRoleAssignment -RoleDefinitionName Reader -ServicePrincipalName $ADApplication.ApplicationId -ErrorAction SilentlyContinue | Out-Null + Write-Host "Completed granting access to AzSK CA SPN on Subscription" -ForegroundColor Green + } + else + { + Write-Host "AzSK CA SPN already have required access on Subscription" -ForegroundColor Green + } + #endregion + } + +} + +#This is the SPN that got created when you setup CA in the central (host) +#subscription in central scan mode. You can get it by calling 'Get-AzSKContinuousAssurance' +#for that subscription (or from the CA log). +$azskSPN = '' #'AzSK_CA_SPN_xxxx' + +#The resource group and storage account will be created at this location. +#Choose the location where your host subscription's 'AzSKRG' is setup. +$loc = '' #'eastus2' + +#This is the target subscription. Each target sub should be similarly 'prepped' +$subId = "" + +#This is the logging option for which the target sub needs to be configured. +$loggingOption = "" +PrepareTargetSubscriptionForCentralModeCA -SubscriptionId $subId -Location $loc -AADAppName $azskSPN -LoggingOption $loggingOption + +``` diff --git a/04-Continous-Assurance/scripts/SetupDatabricksScanJob.md b/04-Continous-Assurance/scripts/SetupDatabricksScanJob.md new file mode 100644 index 00000000..32f9ed0e --- /dev/null +++ b/04-Continous-Assurance/scripts/SetupDatabricksScanJob.md @@ -0,0 +1,194 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +```PowerShell +function InvokeRestAPICall($EndPoint, $Method, $Body,$ErrorMessage) +{ + $uri = $WorkSpaceBaseUrl + $EndPoint + try{ + if([string]::IsNullOrEmpty($body)) + { + $response = Invoke-RestMethod -Method $Method -Uri $uri ` + -Headers @{"Authorization" = "Bearer "+$PersonalAccessToken} ` + -ContentType 'application/json' -UseBasicParsing + }else + { + $response = Invoke-RestMethod -Method $Method -Uri $uri ` + -Headers @{"Authorization" = "Bearer "+$PersonalAccessToken} ` + -ContentType 'application/json' -Body $Body -UseBasicParsing + } + } + catch{ + + Write-Host $ErrorMessage -ForegroundColor RED + throw $_ + } + return $response +} + +function SetupDatabricksScanJob($DatabricksHost) +{ + $WorkSpaceBaseUrl = $DatabricksHost + $PAT = Read-Host -Prompt 'Input Personal Access Token(PAT) for Databricks Workspace' + $PersonalAccessToken = $PAT.Trim() + + # Please don't modify these values + $ConfigBaseUrl = "https://azsdkossep.azureedge.net/3.9.0/" + $NotebookBaseUrl = "https://azsdkossep.azureedge.net/1.0.0/" + $SecretScopeName = "AzSK_CA_Secret_Scope" + $SecretKeyName = "AzSK_CA_Scan_Key" + $NotebookFolderPath = "/AzSK" + # + + #region Step 1: Create Secret Scope + + $params = @{ + 'scope' = $SecretScopeName + } + + $bodyJson = $params | ConvertTo-Json + + # Check if Secret Scope already exists + + Write-Host "Checking if secret scope [$SecretScopeName] already exists in the workspace..." -ForegroundColor Yellow + + $endPoint = "/api/2.0/secrets/scopes/list" + $SecretScopeAlreadyExists = $false + $SecretScopes = InvokeRestAPICall -EndPoint $endPoint -Method "GET" -ErrorMessage "Unable to fetch secret scope, remaining steps will be skipped." + + # todo : check if scopes property exists + if($SecretScopes -ne $null -and ("scopes" -in $SecretScopes.PSobject.Properties.Name) -and ($SecretScopes.scopes | Measure-object).Count -gt 0) + { + $SecretScope = $SecretScopes.scopes | where {$_.name -eq $SecretScopeName} + if($SecretScope -ne $null -and ( $SecretScope | Measure-Object).count -gt 0) + { + $SecretScopeAlreadyExists = $true + Write-Host "Secret scope [$SecretScopeName] already exists in the workspace. We will reuse it." -ForegroundColor Cyan + } + } + + # Create Secret Scope if not already exists + if(-not $SecretScopeAlreadyExists) + { + Write-Host "Creating a new secret scope [$SecretScopeName] in the workspace..." -ForegroundColor Yellow + $endPoint = "/api/2.0/secrets/scopes/create" + $ResponseObject = InvokeRestAPICall -EndPoint $endPoint -Method "POST" -Body $bodyJson -ErrorMessage "Unable to create secret scope, remaining steps will be skipped." + + Write-Host "Created scope [$SecretScopeName] successfully." -ForegroundColor Green + } + + #end region + + #region Step 2: PUT Token in Secret Scope + + # If Secret already exists it will update secret value + + $params = @{ + 'scope' = $SecretScopeName; + "key" = $SecretKeyName; + "string_value" = $PersonalAccessToken + } + + $bodyJson = $params | ConvertTo-Json + + $endPoint = "/api/2.0/secrets/put" + + Write-Host "Creating/Updating value for secret [$SecretKeyName] in the workspace..." -ForegroundColor Yellow + + $ResponseObject = InvokeRestAPICall -EndPoint $endPoint -Method "POST" -Body $bodyJson -ErrorMessage "Unable to create/update secret value, remaining steps will be skipped." + + Write-Host "Created/Updated value for secret [$SecretKeyName] successfully." -ForegroundColor Green + + #end region + + #region Step 3: Set up AzSk Notebook in Databricks workspace + + # Create AzSK folder in user workspace, if folder already exists it will do nothing + + $endPoint = "/api/2.0/workspace/mkdirs" + + $body = @{ + "path" = $NotebookFolderPath + } + + $bodyJson = $body | ConvertTo-Json + + $ResponseObject = InvokeRestAPICall -EndPoint $endPoint -Method "POST" -Body $bodyJson -ErrorMessage "Unable to create folder in workspace, remaining steps will be skipped." + + # Download notebook from server and store it in temp location + + $NotebookServerUrl = $NotebookBaseUrl + "AzSK_CA_Scan_Notebook.ipynb" + $ControlJsonUrl = $ConfigBaseUrl + "DatabricksControls.json" + $filePath = $env:TEMP + "\AzSK_CA_Scan_Notebook.ipynb" + Invoke-RestMethod -Method Get -Uri $NotebookServerUrl -OutFile $filePath + + # Bootstrap basic properties and urls in Notebook + + (Get-Content $filePath) -replace '\#DatabricksHostDomain\#', $WorkSpaceBaseUrl | Set-Content $filePath -Force + (Get-Content $filePath) -replace '\#ControlJsonUrl\#', $ControlJsonUrl | Set-Content $filePath -Force + $fileContent = get-content $filePath + $fileContentBytes = [System.Text.Encoding]::UTF8.GetBytes($fileContent) + $fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes) + + # Import notebook in user workspace, + + $params = @{ + 'path' = $NotebookFolderPath + '/AzSK_CA_Scan_Notebook'; + 'format' = 'JUPYTER'; + 'language' = 'PYTHON'; + 'content'= $fileContentEncoded; + 'overwrite' = 'true' + } + + + $bodyJson = $params | ConvertTo-Json + $endPoint = "/api/2.0/workspace/import" + Write-Host "Importing AzSK_CA_Scan_Notebook into the workspace..." -ForegroundColor Yellow + $ResponseObject = InvokeRestAPICall -EndPoint $endPoint -Method "POST" -Body $bodyJson -ErrorMessage "Unable to import notebook in workspace, remaining steps will be skipped." + Write-Host "Successfully imported AzSK_CA_Scan_Notebook." -ForegroundColor Green + + #cleanup notebook from temp location + + Remove-Item $filePath -ErrorAction Ignore + + #end region + + #region Step 4: Schedule Notebook to run periodically, + + # Check if Job already exists + + Write-Host "Checking if Job AzSK_CA_Scan_Job exists in the workspace..." -ForegroundColor Yellow + $JobAlreadyExists = $false + $endPoint = "/api/2.0/jobs/list" + $JobList = InvokeRestAPICall -EndPoint $endPoint -Method "GET" -ErrorMessage "Unable to list jobs in workspace, remaining steps will be skipped." + + if($JobList -ne $null -and ("jobs" -in $JobList.PSobject.Properties.Name) -and ($JobList.jobs | Measure-object).Count -gt 0) + { + $AzSKJobs = $JobList.jobs | where {$_.settings.name -eq 'AzSK_CA_Scan_Job'} + if($AzSKJobs -ne $null -and ( $AzSKJobs | Measure-Object).count -gt 0) + { + $JobAlreadyExists = $true + Write-Host "AzSK_CA_Scan_Job already exists in the workspace." -ForegroundColor Cyan + } + } + + # Create Job if not already exist + + if(-not $JobAlreadyExists) + { + Write-Host "Creating Job 'AzSK_CA_Scan_Job' in the workspace..." -ForegroundColor Yellow + $JobConfigServerUrl = $ConfigBaseUrl + "DatabricksCAScanJobConfig.json" + $body = Invoke-RestMethod -Method Get -Uri $JobConfigServerUrl + $bodyJson = $body | ConvertTo-Json + $endPoint = "/api/2.0/jobs/create" + $ResponseObject = InvokeRestAPICall -EndPoint $endPoint -Method "POST" -Body $bodyJson -ErrorMessage "Unable to create AzSK_CA_Scan_Job in workspace." + Write-Host "Successfully created Job 'AzSK_CA_Scan_Job' with JobID: $($ResponseObject.job_id)." -ForegroundColor Green + } + + #end region + +} +$databricksHost = "" # for e.g. "https://westus.azuredatabricks.net" +SetupDatabricksScanJob -DatabricksHost $databricksHost + +``` diff --git a/05-Alerting-and-Monitoring/OMSQueries.md b/05-Alerting-and-Monitoring/OMSQueries.md index 953e0777..2e229fab 100644 --- a/05-Alerting-and-Monitoring/OMSQueries.md +++ b/05-Alerting-and-Monitoring/OMSQueries.md @@ -1,9 +1,12 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + ## OMS Helper Queries ### Contents - [Overview](OMSQueries.md#overview) - [Local effective scan result](OMSQueries.md#Local-effective-scan-result) -- [Services scan result for baseline controls](OMSQueries.md#services-scan-result-for-baseline-controls) +- [CA Complete Scan Results](OMSQueries.md#ca-complete-scan-results) -------------------------- ### Overview: @@ -22,40 +25,27 @@ AzSK_CL ``` -------------------------- -### Services scan result for baseline controls: -Following query will help you to check effective scan result for baseline controls +### CA Complete Scan Results +Following query will help you to get complete results generated by CA scan. ``` AIQL -let passStatuslist = AzSK_MetaData_CL -| summarize arg_max(TimeGenerated, *) -| project parsejson(TreatAsPassedStatuses_s); -let baseControlList = AzSK_Inventory_CL -| summarize RunIdentifier_s=max(RunIdentifier_s) by SubscriptionId -| join kind= inner -( - AzSK_Inventory_CL - | where IsBaselineControl_b == true -) -on RunIdentifier_s; -let elevatedAccessControlStatus = AzSK_CL -| where TimeGenerated > ago(90d) and HasAttestationReadPermissions_b == true and HasRequiredAccess_b == true and IsLatestPSModule_b == true and IsBaselineControl_b == true and Tags_s contains "OwnerAccess" -| summarize arg_max(TimeGenerated,ControlStatus_s) by SubscriptionId,ResourceId,ChildResourceName_s,ControlId_s; -let readerAccessControlStatus= AzSK_CL -| where TimeGenerated > ago(3d) and HasAttestationReadPermissions_b == true and HasRequiredAccess_b == true and IsLatestPSModule_b == true and IsBaselineControl_b == true and Tags_s !contains "OwnerAccess" -| summarize arg_max(TimeGenerated,ControlStatus_s) by SubscriptionId,ResourceId,ChildResourceName_s,ControlId_s; -let result = baseControlList -| join kind=leftouter -( - elevatedAccessControlStatus - | union readerAccessControlStatus -) -on SubscriptionId,ResourceId,ControlId_s; -result -| project SubscriptionId,FeatureName_s,ResourceGroupName_s,ResourceName_s,ControlId_s,ControlStatus_s -| extend FinalStatus=iff(ControlStatus_s !in (passStatuslist),"Failed","Passed") -| summarize StatusCount=count() by FinalStatus, SubscriptionId +let uniqueIdentifiers = AzSK_CommandEvent_CL +| where EventName_s == "Command Completed" and PartialScanIdentifier_s != "" +| summarize arg_max(TimeGenerated, *) by SubscriptionId +| project PartialScanIdentifier_s; +AzSK_CL | join kind= inner ( + uniqueIdentifiers +) on PartialScanIdentifier_s +| extend ControlStatus = iff(ControlStatus_s == "Passed", "Passed","Failed") +| summarize AggregatedValue = count() by SubscriptionId,ControlStatus ``` +-------------------------- +### Get expiring CA cert details +Following query will give you details of subscriptions CA for which CA certificate is going to expire within 7 days - +``` AIQL +AzSKMetaData_CL | where TimeGenerated > ago(15d) | summarize arg_max(TimeGenerated, *) by SubscriptionId | where CACertExpiryTime_t < ago(-7d) +| project SubscriptionId, SubscriptionName_s, CACertExpiryTime_t +``` diff --git a/05-Alerting-and-Monitoring/Readme.md b/05-Alerting-and-Monitoring/Readme.md index 8d7a068d..6182f9da 100644 --- a/05-Alerting-and-Monitoring/Readme.md +++ b/05-Alerting-and-Monitoring/Readme.md @@ -1,19 +1,31 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + +>NOTE: +>The OMS* parameter/variable names will soon be deprecated. Please ensure that you have made the necessary changes to CA, CICD and AzSK Monitoring Solution as per below: +> 1. Updated CA setups with new names ([details here](../04-Continous-Assurance#updating-an-existing-continuous-assurance-setup)). (Not required for CSEO subscriptions!) +> 2. Switched to new names in CICD extension ([details here](../03-Security-In-CICD#advanced-cicd-scanning-capabilities)). (Required for all subscriptions) +> 3. Start using the new parameters for [CA](../04-Continous-Assurance#setting-up-continuous-assurance---step-by-step) and [AzSK Monitoring Solution](../05-Alerting-and-Monitoring#1-c). + # Alerting & Monitoring -![Alert_Monitoring](../Images/Alerting_and_Monitoring.PNG) +![Alerting_and_Monitoring](../Images/Alerting_and_Monitoring.png) -## OMS Solution for AzSK +## Monitoring Solution for AzSK ### Contents - [Overview](Readme.md#overview) -- [Components of the AzSK OMS Solution](Readme.md#components-of-the-azsk-oms-solution) -- [Setting up the AzSK OMS Solution (Step by Step)](Readme.md#setting-up-the-azsk-oms-solution-step-by-step) -- [Guide to AzSK OMS Solution queries](Readme.md#guide-to-azsk-oms-solution-queries) +- [Components of the AzSK Monitoring Solution](Readme.md#components-of-the-azsk-monitoring-solution) +- [Setting up the AzSK Monitoring Solution (Step by Step)](Readme.md#setting-up-the-azsk-monitoring-solution-step-by-step) +- [Guide to AzSK Monitoring Solution queries](Readme.md#guide-to-azsk-monitoring-solution-queries) - [Next Steps](Readme.md#next-steps) - [Appendix](Readme.md#appendix) - - [Creating an OMS workspace](Readme.md#a-creating-an-oms-workspace) - - [Testing OMS connectivity](Readme.md#b-testing-oms-connectivity) - - [Routing AzSK events to OMS](Readme.md#c-routing-azsk-events-to-oms) - - [Leveraging other OMS Solutions from the Solutions Gallery](Readme.md#d-leveraging-other-oms-solutions-from-the-solutions-gallery) + - [Creating a Log Analytics workspace](Readme.md#a-creating-a-log-analytics-workspace) + - [Testing Log Analytics workspace connectivity](Readme.md#b-testing-log-anaytics-workspace-connectivity) + - [Routing AzSK events to Log Analytics](Readme.md#c-routing-azsk-events-to-log-analytics) + - [Leveraging other Management Solutions from the Azure Marketplace](Readme.md#d-leveraging-other-management-solutions-from-the-azure-marketplace) -------------------------- ### Overview: @@ -22,169 +34,157 @@ The Alerting & Monitoring features of AzSK empower dev ops teams with the follow - visibility to control status for their Azure subscription and critical enterprise/application resources - pre-configured search queries for creating alerts to facilitate action on security drift -Out of the box, these capabilities can be leveraged via the Operations Management Suite (OMS) solution in AzSK. +Out of the box, these capabilities can be leveraged via the Log Analytics-based Monitoring solution in AzSK. However, a dev ops team can equally easily leverage a different system for log analytics (e.g., Splunk) and view the AzSK control evaluation events -in the alternate system. This can be accomplished by using via connectors for Event Hubs or Webhooks in the AzSK. +in the alternate system. This can be accomplished by using connectors for Event Hubs or Webhooks in the AzSK. [Back to top…](Readme.md#contents) -### Components of the AzSK OMS Solution -The AzSK OMS Solution is deployed to an OMS workspace that is used by the dev ops team for monitoring and -generates a dashboard for security monitoring and alerting based on AzSK control evaluation events. +### Components of the AzSK Monitoring Solution +The AzSK Monitoring Solution is deployed to a Log Analytics workspace that is used by the dev ops team for monitoring and +generating a dashboard for security monitoring and alerting based on AzSK control evaluation events. -The out of box security dashboard generated by the AzSK OMS solution includes: -1. A summary tile for the main OMS dashboard (home view) -2. A detailed view comprised of multiple blades displaying security control status for your: +The out of box security dashboard generated by the AzSK Monitoring Solution includes: +1. An "Overview tile" for the Log Analytics workspace summary (Home view) +2. A detailed "View dashboard" comprised of multiple blades displaying security control status for your: a) subscription, b) express route networks and c) other cloud resources (shown with various pivots) -3. Ready to use log search queries for security drift conditions +3. Ready to use Logs queries for security drift conditions -![05_Application_Security_View](../Images/05_OMS_New_View.PNG) +![05_Application_Security_View](../Images/05_Application_Security_View.png) [Back to top…](Readme.md#contents) -### Setting up the AzSK OMS Solution (Step by Step) -This section will walk you through the step-by-step experience of setting up the AzSK OMS solution. +### Setting up the AzSK Monitoring Solution (Step by Step) +This section will walk you through the step-by-step experience of setting up the AzSK Monitoring Solution. -Note that for the OMS solution to display anything, you have to configure AzSK in SDL or CICD or -CA mode to send events to the target OMS workspace as mentioned in the "Routing Events to OMS..." section above. +Note that for the Monitoring Solution to display anything, you have to configure AzSK in SDL or CICD or +CA mode to send events to the target Log Analytics workspace as mentioned [here](Readme.md#c-routing-azsk-events-to-log-analytics). -If you do not have an OMS workspace yet, see [Appendix](Readme.md#appendix) to create one. +If you do not have a Log Analytics workspace yet, see [Appendix](Readme.md#appendix) to create one. The rest of this section assumes that: -a) you have an OMS worskpace** +a) you have a Log Analytics worskpace** b) you have setup AzSK to send events to that workspace (from one or more of SDL, CICD, CA stages) -c) some AzSK scans have run in respective stages and events are already present in the OMS workspace +c) some AzSK scans have run in respective stages and events are already present in the Log Analytics workspace If you need help for any of the above, see the respective section in the [Appendix](Readme.md#appendix) at the bottom. -** The OMS product team has recently made several improvements to the underlying store and have also adopted -a new query language. This write-up assumes that you are using the new/updated OMS workspace and -the new query language. If you have not migrated yet, we will also provide the corresponding old -language queries. (All images will show queries using the new language though!) - -The AzSK OMS setup involves two sets of steps - one set to be run by the monitoring team that owns -the OMS workspace and the other set to be run by the application team (for applications which -are to be monitored via a common OMS dashboard). +The AzSK Monitoring setup involves two sets of steps - one set to be run by the monitoring team that owns +the Log Analytics workspace and the other set to be run by the application team (for applications which +are to be monitored via a common Log Analytics dashboard). We will refer to the monitoring team as the "**Ops team**" and the application team as the "**App team**" below. The general model assumed is one where there are (1) multiple subscriptions covering a -portfolio of applications for a business unit and (2) a central subscription that hosts the OMS -workspace for that business unit. We call the former subscriptions the 'app subscriptions' and -the latter the 'OMS subscription'. +portfolio of applications for a business unit and (2) a central subscription that hosts the Log Analytics workspace for that business unit. We call the former the 'app subscriptions' and +the latter the 'Log Analytics subscription'. > **Note**: This is not to suggest a hard separation of roles between the actual individuals -involved. Indeed, most dev ops teams will have dev rotating to support ops and vice versa.) +involved. Indeed, most dev ops teams will have Dev rotating to support Ops and vice versa.) -**Step-1 (Ops Team): Deploy the AzSK OMS Solution** +### Step-1 (Ops Team): Deploy the AzSK Monitoring Solution -**[1-a]** Use Set-AzureRmContext to choose the subscription corresponding to the OMS workspace and run the command below -to get the details about your OMS workspace: +### [1-a] +Use Set-AzContext to choose the subscription corresponding to the Log Analytics workspace and run the command below +to get the details about your Log Analytics workspace: ```PowerShell - Set-AzureRmContext -SubscriptionId '' #switch to the OMS subscription - Get-AzureRmOperationalInsightsWorkspace #get info about the OMS workspace (we'll need that below) + Set-AzContext -SubscriptionId '' #switch to the Log Analytics subscription + Get-AzOperationalInsightsWorkspace #get info about the Log Analytics workspace (we'll need that below) ``` -This outputs the OMS workspaces from the OMS subscription as shown below: +This outputs the Log Analytics workspaces from the Log Analytics subscription as shown below: -![05_Get_AzureRmOperationalInsightsWorkspace](../Images/05_Get_AzureRmOperationalInsightsWorkspace.PNG) +![05_Get_AzOperationalInsightsWorkspace](../Images/05_Get_AzOperationalInsightsWorkspace.png) -**[1-b]** Obtain the workspaceId and sharedKey for the OMS workspace you'd like to use for monitoring. -Click on "Settings" (gear wheel on the top band) for the OMS workspace and navigate to -"Connected Sources -> Windows Servers" as shown in the image below: +### [1-b] +Obtain the workspaceId and sharedKey for the Log Analytics workspace you'd like to use for monitoring. +Go to the Log Analytics workspace and navigate to "Advanced Settings -> Connected Sources -> Windows Servers" as shown in the image below: +> **Note**: The "Advanced Settings" option will be visible only if you have 'Owners' access (and have elevated to Owner if using PIM). It will not be visible if you are 'Reader'. -![05_Setting_OMS_Workspace_Primary_Key](../Images/05_OMS_WsId_ShrKey.PNG) +![05_Log_Analytics_Workspace_WsId_ShrKey](../Images/05_Log_Analytics_Workspace_WsId_ShrKey.png) -**[1-c]** -Run the below commands in PS after replacing the various '<>' with - (a) respective values for the OMS workspace to be used - and (b) a unique name to identify the view with in the OMS home dashboard. +### [1-c] +Run the commands below in PS after replacing the various '<>' with + (a) respective values for the Log Analytics workspace to be used + and (b) a unique name to identify the view with in the Log Analytics workspace summary (Overview). ```PowerShell - $omsSubId ='' #subscription hosting the OMS workspace - $omsWSId ='' - $omsRGName ='' #RG where the OMS workspace is hosted (See 1-a) - $azSkViewName = '' #This will identify the tile for AzSK view in OMS. E.g., MyApp-View-1 + $lawsSubId ='' #subscription hosting the Log Analytics workspace + $lawsId ='' + $lawsRGName ='' #RG where the Log Analytics workspace is hosted (See 1-a) + $azSkViewName = '' #This will identify the tile for AzSK view in Log Analytics workspace. E.g., MyApp-View-1 - #This command will deploy the AzSK view in the OMS workspace. Happy monitoring!   - Install-AzSKOMSSolution -OMSSubscriptionId $omsSubId ` -                    -OMSResourceGroup $omsRGName ` -                    -OMSWorkspaceId $omsWSId ` - -ViewName $azSkViewName + #This command will deploy the AzSK view in the Log Analytics workspace. Happy monitoring!   + Install-AzSKMonitoringSolution -LAWSSubscriptionId $lawsSubId ` +                    -LAWSResourceGroup $lawsRGName ` +                    -WorkspaceId $lawsId ` + -ViewName $azSkViewName [-Force] ``` -> Note: If you are on the old model for OMS, you should use the following command instead: -> ```PowerShell -> #Install command for *old* model of OMS -> Install-AzSKOMSSolution -OMSSubscriptionId $omsSubId ` -> -OMSResourceGroup $omsRGName ` -> -OMSWorkspaceId $omsWSId ` -> -ViewName $azSkViewName ` -> -UseOldModel ` -> -OMSInstallationOption GenericView -> -The table below explains the different parameters used by Install-AzSKOMSSolution cmdlet: +The table below explains the different parameters used by Install-AzSKMonitoringSolution cmdlet: |ParameterName|Comments| | ----- | ---- | -|OMSSubscriptionId|Id of the subscription where the OMS workspace is hosted| -|OMSResourceGroup|Name of the resource group where the OMS workspace is hosted| -|OMSWorkspaceId|Workspace ID of the OMS workspace name which will be used for monitoring| -|ViewName|Name of the AzSK OMS view (unique per OMS workspace)| +|LAWSSubscriptionId|Id of the subscription where the Log Analytics workspace is hosted| +|LAWSResourceGroup|Name of the resource group where the Log Analytics workspace is hosted| +|WorkspaceId|Workspace ID of the Log Analytics workspace name which will be used for monitoring| +|ViewName|Name of the AzSK Log Analytics Workspace summary (Overview) (unique per Log Analytics workspace)| +|Force|Provide this switch to force deployment without further user consent (Optional)| -> Note: A resource group name such as 'mms-xxx' is used by default by the OMS setup process (where 'xxx' can +> Note: A resource group name such as 'mms-xxx' is used by default by the Monitoring setup process (where 'xxx' can be 'eus' or 'sea' etc. based on the region). If you specified a custom resource group name when creating -the OMS workspace, then remember to use *that* name in the install command above. +the Log Analytics workspace, then remember to use *that* name in the install command above. If you forgot the custom resource group name you used, you can always use -Get-AzureRmOperationalInsightsWorkspace to see the correct value to use for -the respective OMS workspace. +Get-AzOperationalInsightsWorkspace to see the correct value to use for +the respective Log Analytics workspace. The installation command will display output like the below: -![05_Install-AzSKOMSSecurityPack](../Images/05_Install-OMSSolution_output.PNG) +![05_Install-AzSKMonitoringSolution](../Images/05_Install-AzSKMonitoringSolution.png) -At this point, assuming that AzSK events were already being sent to the OMS workspace, you should start +At this point, assuming that AzSK events were already being sent to the Log Analytics workspace, you should start seeing a tile such as the one below: -![05_Setting_OMS_Workspace_Subscription_View_Artifacts](../Images/05_Main_Dashboard_View.PNG) +![05_Workspace_Summary_View](../Images/05_Workspace_Summary_View.png) -**Step-2 (Ops Team): Using the OMS view for monitoring** +**Step-2 (Ops Team): Using the Log Analytics Workspace Summary (Overview) for monitoring** **2 (a)** Viewing raw events from AzSK (sanity check) -Click on the 'magnifier' icon in the taskbar on the left to open the "Log Search" page. +Click on the 'Logs' in the menu bar on the left to open the "Logs" query page. Enter "AzSK_CL" in the query field. (Old query: "Type=AzSK_CL") You should see data about AzSK events as query results. (Again, this assumes that by now AzSK -control scan results are being sent to this workspace. See Section-B in Appendix further below for +control scan results are being sent to this workspace. See [this](Readme.md#b-testing-log-anaytics-workspace-connectivity) for how that is done.) -![05_Setting_OMS_Workspace_Log_Search_Query](../Images/05_OMS_Log_Search_Query.PNG) -If you are certain that events are being sent to the OMS but you are seeing blank views/no query results, -you may need to extend the duration applicable to the queries. (This can be done using the drop-down to -the left of the bell icon in the topmost band in the dashboard.) +![05_Log_Analytics_Workspace_Logs_Query](../Images/05_Log_Analytics_Workspace_Logs_Query.png) -![05_Setting_OMS_Workspace_Log_Search](../Images/05_OMS_Query_Duration.PNG) +If you are certain that events are being sent to the Log Analytics workspace but you are seeing blank views/no query results, +you may need to extend the duration applicable to the queries. (This can be done using the 'Time range' selector next to the 'Run' button at the top of the query window.) + +![05_Log_Analytics_Workspace_Query_Duration](../Images/05_Log_Analytics_Workspace_Query_Duration.png) -**2 (b)** Using the AzSK Solution +**2 (b)** Using the AzSK Monitoring Solution The solution view contains multiple blades representing alerts, various types of security activity, security trends, etc. This view shows up when you click on the view tile and looks like the picture below: -![05_Setting_OMS_Workspace_Solution_View](../Images/05_OMS_View.PNG) + +![05_Log_Analytics_Workspace_New_View](../Images/05_Log_Analytics_Workspace_New_View.png) The very first (Summary) blade provides complete instructions on how to interpret the different blades in this view. These blades cover the complete picture of baseline security compliance @@ -199,23 +199,22 @@ As shown in the image below, you can dive deeper into a specific control failure the AzSK control event for details such as severity, controlId, recommendation, etc. These are the same fields that display in the CSV file when you run the AzSK manually as a developer. -![05_Setting_OMS_Workspace_Solution_View](../Images/05_OMS_Control_Failure.PNG) +![05_Log_Analytics_Control_Failure](../Images/05_Log_Analytics_Control_Failure.png) [Back to top…](Readme.md#contents) -### Guide to AzSK OMS Solution queries -This section walks you through the queries present in the AzSK OMS solution. To get the latest queries make sure that you have the latest solution installed in your OMS workspace. To get the latest version of solution you need to re-install OMS solution using step **[[1-c]](https://github.com/azsdk/azsdk-docs/blob/master/05-Alerting-and-Monitoring/Readme.md#setting-up-the-azsk-oms-solution-step-by-step)** mentioned above. The queries show the status of controls based on the following criteria. -- Each blade shows the aggregated control status for all subscriptions whose data is sent to the OMS workspace. +### Guide to AzSK Monitoring Solution queries +This section walks you through the queries present in the AzSK Monitoring solution. To get the latest queries make sure that you have the latest solution installed in your Log Analytics workspace. To get the latest version of solution you need to re-install Monitoring solution using step **[[1-c]](#1-c)** mentioned above. The queries show the status of controls based on the following criteria. +- Each blade shows the aggregated control status for all subscriptions whose data is sent to the Log Analytics workspace. - By default, each blade shows the status of baseline controls. -- The queries show counts based on control status recieved for last scan data(done with required access) received by the OMS workspace. +- The queries show counts based on control status received for last scan data(done with required access) received by the Log Analytics workspace. - Any control status other than "Passed" is treated as "Failed"(including "Verify",Manual,etc.) in queries for calculating failure counts. Details of various blades of Azure Security Health View are as follows: -**1) Subsciption Security Status:** This blade shows the status of baseline Subsciption Security controls of your subscription(s).The below image depicts the blade: +**1) Subscription Security Status:** This blade shows the status of baseline Subscription Security controls of your subscription(s). -![](/Images/OMS_Blade_SS.PNG) +- Donut: The query below shows the aggregated control status of Subscription Security controls. -- Donut: The below query shows the aggregated control status of Subscription Security controls. ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -226,7 +225,9 @@ Details of various blades of Azure Security Health View are as follows: | summarize count() by SubscriptionId,ControlId_s,ControlStatus | summarize AggregatedValue = count() by ControlStatus | sort by AggregatedValue desc -- List: The below query shows the list of subscriptions that have one or more Subscription Security controls failing along with the number of controls failing on each subscription. + ``` +- List: The query below shows the list of subscriptions that have one or more Subscription Security controls failing along with the number of controls failing on each subscription. + ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -238,12 +239,12 @@ Details of various blades of Azure Security Health View are as follows: | summarize count() by SubscriptionName_s,ControlId_s,ControlStatus_s | summarize AggregatedValue = count() by SubscriptionName_s | sort by AggregatedValue desc + ``` -**2) Express Route vNet Security Status:** This blade shows the status of baseline ERvNet Controls for virtual networks in your subscription that have Express Route connectivity setup.The below image depicts the blade: +**2) Express Route vNet Security Status:** This blade shows the status of baseline ERvNet Controls for virtual networks in your subscription that have Express Route connectivity setup. -![](/Images/OMS_Blade_ERvNet.PNG) +- Donut: The query below shows the aggregated control status of ERvNet controls. -- Donut: The below query shows the aggregated control status of ERvNet controls. ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -253,7 +254,9 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated,*) by SubscriptionName_s,ResourceId,ControlId_s | summarize AggregatedValue = count() by ControlStatus | sort by AggregatedValue desc -- List: The below query shows the list of subscriptions that have one or more ERvNet control failing and number of failures on each subscription. + ``` +- List: The query below shows the list of subscriptions that have one or more ERvNet control failing and number of failures on each subscription. + ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -264,12 +267,14 @@ Details of various blades of Azure Security Health View are as follows: | where ControlStatus =="Failed" | summarize AggregatedValue = count() by SubscriptionName_s | sort by AggregatedValue desc + ``` **3) Resource Security (RS-1):** This blade shows the status of baseline controls for all resources present on your subscription(s). The below image depicts the blade: -![](/Images/OMS_Blade_RS1.PNG) +![05_Log_Analytics_Blade_RS1](/Images/05_Log_Analytics_Blade_RS1.PNG) + +- Donut: The query below shows the aggregated status of controls for all the resources present on your subscription(s). -- Donut: The below query shows the aggregated status of controls for all the resources present on your subscription(s). ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -279,7 +284,9 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated, *) by SubscriptionId, ResourceId, ControlId_s | summarize AggregatedValue = count() by ControlStatus | sort by AggregatedValue desc -- List: The below query shows the list of resource type that have one or more control failing along with the number of controls failing for each resource type. + ``` +- List: The query below shows the list of resource type that have one or more control failing along with the number of controls failing for each resource type. + ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -289,12 +296,14 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated, *) by SubscriptionId, ResourceId, ControlId_s | where ControlStatus == "Failed" | summarize AggregatedValue = count() by FeatureName_s | sort by AggregatedValue desc + ``` **4) Resource Security (RS-2):** This blade shows resources present on your subscription(s) that have some baseline controls failing. The below image depicts the blade: -![](/Images/OMS_Blade_RS2.PNG) +![05_Log_Analytics_Blade_RS2](/Images/05_Log_Analytics_Blade_RS2.PNG) + +- Tile: The query below shows the number of unique resources that have at least one control failing. -- Tile: The below query shows the number of unique resources that have at least one control failing. ``` AIQL AzSK_CL | where TimeGenerated >ago(3d) @@ -305,7 +314,9 @@ Details of various blades of Azure Security Health View are as follows: | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ResourceName_s | count -- List: The below query shows the the list of resources that have one or more control failing along with the number of failed controls for each resource. + ``` +- List: The query below shows the the list of resources that have one or more control failing along with the number of failed controls for each resource. + ``` AIQL AzSK_CL | where TimeGenerated >ago(3d) @@ -315,12 +326,14 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated, *) by SubscriptionId, ResourceId, ControlId_s | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ResourceName_s + ``` **5) Resource Security (RS-3):** This blade shows resource groups present on your subscription(s) that failed baseline controls. The below image depicts the blade: -![](/Images/OMS_Blade_RS3.PNG) +![05_Log_Analytics_Blade_RS3](/Images/05_Log_Analytics_Blade_RS3.PNG) + +- Tile: The query below shows the number of unique resource groups containing resources that are failing. -- Tile: The below query shows the number of unique resource groups containing resources that are failing. ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -331,7 +344,9 @@ Details of various blades of Azure Security Health View are as follows: | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ResourceGroup | count -- List: The below query shows list of resource groups that have one or more controls failing along with the number of failed controls for each resource group. + ``` +- List: The query below shows list of resource groups that have one or more controls failing along with the number of failed controls for each resource group. + ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -341,12 +356,14 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated, *) by SubscriptionId, ResourceId, ControlId_s | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ResourceGroup + ``` **6) Resource Security (RS-4):** This blade shows baseline security controls that are failing on your subscription(s). The below image depicts the blade: -![](/Images/OMS_Blade_RS4.PNG) +![05_Log_Analytics_Blade_RS4](/Images/05_Log_Analytics_Blade_RS4.PNG) + +- Tile: The query below shows the number of unique controls that are failing. -- Tile: The below query shows the number of unique controls that are failing. ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -357,7 +374,9 @@ Details of various blades of Azure Security Health View are as follows: | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ControlId_s | count -- List: The below query shows the list of controls that are failing along with the number of failures for each control. + ``` +- List: The query below shows the list of controls that are failing along with the number of failures for each control. + ``` AIQL AzSK_CL | where TimeGenerated > ago(3d) @@ -367,26 +386,27 @@ Details of various blades of Azure Security Health View are as follows: | summarize arg_max(TimeGenerated, *) by SubscriptionId, ResourceId, ControlId_s | where ControlStatus == "Failed" | summarize AggregatedValue = count() by ControlId_s + ``` **7) Useful Queries:** In this last blade, we have included a few queries that you can use as is or tweak to create your own custom queries. These queries are similar to the queries for various other blades except that they will show the status of **all controls** (opposed to baseline controls only). These can be used as a starting point for setting up your own alerts, doing auto-heal, etc. [Back to top…](Readme.md#contents) ### Next Steps -Assuming that you have setup the OMS solution and configured AzSK control event routing from one or more of +Assuming that you have setup the AzSK Monitoring solution and configured AzSK control event routing from one or more of the dev ops stages (developer machines (SDL stage), your build environment (CICD stage) and operational environment (CA)) -with the appropriate OMS settings, you are all set to monitor and act on security issues/drift for your +with the appropriate Log Analytics settings, you are all set to monitor and act on security issues/drift for your cloud subscription and (application) resources across the multiple stages of dev ops. -As next steps, you can modify, customize and enhance the default AzSK OMS solution in several interesting ways. +As next steps, you can modify, customize and enhance the default AzSK Monitoring solution in several interesting ways. Here are some interesting ideas to pursue: ***Create additional search queries*** -Out of the box, the AzSK OMS solution provides some common search queries you may find useful. However, you can -use the OMS query language to create and save your own queries that you may find valuable towards monitoring. +Out of the box, the AzSK Monitoring solution provides some common search queries you may find useful. However, you can +use the Azure Monitor Logs to create and save your own queries that you may find valuable towards monitoring. -***Setup Alerts in OMS*** -Based on threat modeling for critical, alertworthy conditions, you can setup OMS alerts based on search +***Setup Alerts in Log Analytics*** +Based on threat modeling for critical, alertworthy conditions, you can setup Microsoft Azure alerts based on search queries. These alerts can be raised over Email or SMS or can also trigger some action (e.g., an auto-correct script) via webhooks/runbooks. (For instance, if you know that a particular storage account contains extremely sensitive data, you can define a search query and a respective alert for any hint of abnormal activity on that storage account.) @@ -399,7 +419,7 @@ in the AzSK scan commands such as Get-AzSKAzureServicesSecurityStatus. ***Create views application-centric views*** You can start by cloning the default view and make modifications to the queries underpinning the individual blades -to make your own custom views. For example, you can modify the cloned view to monitor specific applications using the AzSK OMS solution. +to make your own custom views. For example, you can modify the cloned view to monitor specific applications using the AzSK Monitoring solution. This can be done simply by filtering the default queries underpinning the blades by resource groups corresponding to one or more applications. You could monitor all apps via different blades in the same view or create multiple views - one for each application. @@ -411,70 +431,55 @@ corresponding to different dev ops stages ("SDL", "CICD", "CA") in respective bl (Note: Events from CA appear with a source tag of "CC" which stands for 'Continuous Compliance' the older name for "Continuous Assurance".) -![05_Setting_OMS_Workspace_App_Specific_View_Details_2](../Images/05_Setting_OMS_Workspace_App_Specific_View_Details_2.PNG) +![05_Setting_Log_Analytics_Workspace_App_Specific_View_Details](../Images/05_Setting_Log_Analytics_Workspace_App_Specific_View_Details.png) - [Back to top…](Readme.md#contents) -------------------------- ## Appendix ## -### [A] Creating an OMS workspace ### -**Step-1 (Ops team):** Create a new OMS workspace. +### [A] Creating a Log Analytics workspace ### +**Step-1 (Ops team):** Create a new Log Analytics workspace. -Go to https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-get-started and follow the simple steps to create a new OMS workspace. - -(The steps below are slightly dated but still work.) -![05_Setting_OMS_Workspace_New_OMS](../Images/05_Setting_OMS_Workspace_New_OMS.PNG) +Go [here](https://docs.microsoft.com/en-in/azure/azure-monitor/learn/quick-create-workspace) and follow the simple steps to create a new Log Analytics workspace. + +![05_Setting_New_Log_Analytics_Workspace](../Images/05_Setting_New_Log_Analytics_Workspace.png) -**Note:** If you already have an OMS workspace that is used for other monitoring activities, -then, ideally, the same workspace should be used for setting up the AzSK OMS solution as well. +**Note:** If you already have a Log Analytics workspace that is used for other monitoring activities, +then, ideally, the same workspace should be used for setting up the AzSK Monitoring solution as well. The idea is that the security views appear alongside other views on the 'general' operations dashboard and not in a standalone one. -**Step-2 (Ops Team):** Associate with an Azure Subscription. - -This should be the central subscription that is to host the OMS workspace. - -![05_Setting_OMS_Workspace_Select_Subscription](../Images/05_Setting_OMS_Workspace_Select_sub.PNG) - -After concluding setup for the OMS workspace, you will also get an email for email -address confirmation such as the one below: +**Step-2 (Ops Team):** Capture the Workspace ID and Primary Key for the Log Analytics workspace by navigating to "Advanced Settings -> Connected Sources -> Windows Servers". -![05_Setting_OMS_Workspace_Email_Confirmation](../Images/05_Setting_OMS_Workspace_Email_Confirmation.PNG) +![05_Log_Analytics_Workspace_WsId_ShrKey](../Images/05_Log_Analytics_Workspace_WsId_ShrKey.png) -**Step-3 (Ops Team):** Capture the WorkspaceID and PrimaryKey for the workspace by clicking on -"Settings" for the OMS workspace and navigating to "Connected Sources -> Windows Servers". -![05_Setting_OMS_Workspace_Primary_Key](../Images/05_OMS_WsId_ShrKey.PNG) - - - -### [B] Testing OMS connectivity ### -Let us look at how to send events to OMS from AzSK running on a local machine. This is a handy way to -test OMS connectivity and also to see if the AzSK OMS view can display the received events. +### [B] Testing Log Anaytics workspace connectivity ### +Let us look at how to send events to the Log Analytics workspace from AzSK running on a local machine. This is a handy way to +test connectivity and to see if the Logs can display the received events. **Step-1 (App Team):** -Connect the local (dev box) installation of AzSK to your OMS workspace for sending AzSK control evaluation events. +Connect the local (dev box) installation of AzSK to your Log Analytics workspace for sending AzSK control evaluation events. Run the below in a PS session after logging in to Azure (this assumes that you have the latest AzSK installed). ```PowerShell - $wsID = 'oms_workspace_id_here' #See pictures in [A] above for how to get wsId and shrKey - $shrKey = 'workspace_sharedKey_here' + $wsID = 'workspace_ID_here' #See pictures in [A] above for how to get wsId and shrKey + $shrKey = 'workspace_PrimaryKey_here' - Set-AzSKOMSSettings -OMSWorkspaceID $wsID -OMSSharedKey $shrKey + Set-AzSKMonitoringSettings -WorkspaceID $wsID -SharedKey $shrKey ``` Close the current PS window and start a new one. (This is required for the new settings to take effect.) After this, all AzSK cmdlets, SVTs, etc. run on the local machine will start sending events (outcomes of -security scans) into the OMS repository corresponding to the workspaceID above. +security scans) into the Log Analytics repository corresponding to the workspace ID above. -**Step-2 (App Team):** Generate some AzSK events and validate that they are reaching the configured OMS workspace. +**Step-2 (App Team):** Generate some AzSK events and validate that they are reaching the configured Log Analytics workspace. -Run a few AzSK cmdlets to generate events for the OMS repo. +Run a few AzSK cmdlets to generate events for the Log Analytics repo. For example, you can run one or both of the following: ```PowerShell @@ -482,91 +487,84 @@ For example, you can run one or both of the following: Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subID -ResourceGroupNames 'app_rg_name' ``` -After the above scans finish, if we go into OMS Log Search and search for 'AzSK_CL', it should show +After the above scans finish, if we go into Log Analytics workspace Logs and search for 'AzSK_CL', it should show AzSK events similar to the below ("_CL" stands for "custom log"): -![05_Setting_OMS_Workspace_Custom_Log](../Images/05_Setting_OMS_Workspace_Custom_Log.PNG) +![05_Setting_Log_Analytics_Workspace_Custom_Log](../Images/05_Setting_Log_Analytics_Workspace_Custom_Log.png) -If you have already set the AzSK OMS solution up, you will also be able to see these in pictorial form -in the AzSK OMS view. However, the OMS view can be setup later as it is not required just to check if -the events are being sent into the OMS workspace. +If you have already set the AzSK Monitoring solution up, you will also be able to see these in pictorial form +in the AzSK Log Analytics Workspace Summary (Overview). However, the workspace summary can be setup later as it is not required just to check if +the events are being sent into the Log Analytics workspace. -### [C] Routing AzSK events to OMS +### [C] Routing AzSK events to Log Analytics Note that the Security Verification Tests (SVTs) from AzSK can be run in 3 stages: 1. Development (referred to as "SDL") 2. Build/Deployment ("CICD") 3. Continuous Assurance ("CA") The results of control evaluation generated by running AzSK SVTs in **all** of these stages can be -(independently) sent to OMS. Depending on the dev ops stage the mechanism used to 'wire up' AzSK with OMS is different. +(independently) sent to Log Analytics. Depending on the dev ops stage the mechanism used to 'wire up' AzSK with Log Analytics is different. -1. In the development ("SDL") stage, the following command can be used to set the OMS workspace that will collect events +1. In the development ("SDL") stage, the following command can be used to set the Log Analytics workspace that will collect events generated via various AzSK-scripts/SVTs etc. in a subscription: ```PowerShell - Set-AzSKOMSSettings -OMSWorkspaceID -OMSSharedKey + Set-AzSKMonitoringSettings -WorkspaceId -SharedKey ``` Basically, after the above command is run (once) on your desktop, subsequent AzSK SVT control evaluation events will be sent -to the OMS workspace configured above. +to the Log Analytics workspace configured above. > Note: You will need to close and reopen PS session after running the above command for the setting change to take effect. -2. In the build/deployment (CICD) stage, OMS settings are specified via input parameters for the [AzSK SVTs build/release extension](../03-Security-In-CICD/Readme.md). +2. In the build/deployment (CICD) stage, Log Analytics settings are specified via input parameters for the [AzSK SVTs build/release extension](../03-Security-In-CICD/Readme.md#adding-svts-in-the-release-pipeline). -3. For Continuous Assurance (CA), the OMS workspace info is specified in the input parameters of the [Continuous Assurance setup script](../04-Continous-Assurance/Readme.md). +3. For Continuous Assurance (CA), the Log Analytics workspace info is specified in the input parameters of the [Continuous Assurance setup script](../04-Continous-Assurance/Readme.md#setting-up-continuous-assurance---step-by-step). -Events sent from these (different devops) stages of one or more applications get aggregated -in the OMS workspace alongside events from various out-of-box solutions available in the OMS gallery. +Events sent from these (different dev ops) stages of one or more applications get aggregated +in the Log Analytics workspace alongside events from various out-of-box solutions available in the Log Analytics Solution gallery. Overall, this provides a single pane view of the security across the entire set of cloud resources in a subscription. A schematic of this (aggregate view model) is shown below: -> Note AzSK control evaluation results (AzSK events) show up as Type=AzSK_CL in the OMS workspace. - -![05_Aggregate_View_of_security_in_OMS](../Images/05_Aggregate_View_of_security_in_OMS.PNG) +> Note AzSK control evaluation results (AzSK events) show up as Type=AzSK_CL in the Log Analytics workspace. [Back to top…](Readme.md#contents) -### [D] Leveraging other OMS Solutions from the Solutions Gallery ### -The OMS Solution Gallery contains several out of the box solutions that are invaluable to use towards +### [D] Leveraging other Management Solutions from the Azure Marketplace ### +The Azure Monitor contains several out of the box solutions that are invaluable to use towards a comprehensive coverage of monitoring and alerts of various Azure resource types. Many resources generate -a rich set of 'data plane' diagnostics and logs which can be routed into an OMS dashboard for monitoring +a rich set of 'data plane' diagnostics and logs which can be routed into a Log Analytics dashboard for monitoring using these solutions. In the part, we will look at how to leverage a couple of common solutions. You can add more based on the specific resources (SQL, VM, Service Fabric, Key Vault, etc.) you are using in your subscription. The AzSK solution complements the coverage from these individual solutions by its focus on cloud resource configuration. -It is also unique it its coverage of events across dev ops stages. +It is also unique in its coverage of events across dev ops stages. +You can read more about intalling a Management Solution to Log Analytics workspace [here](https://docs.microsoft.com/en-in/azure/azure-monitor/insights/solutions#install-a-management-solution). +> **Note**: Setting up other solutions from the Azure Marketplace is not required for the AzSK Monitoring Solution to work. -> **Note**: Setting up other solutions from the gallery is not required for the AzSK OMS Solution to work. +**Step-1: Optional** (Ops Team) Configure alerts on Analytics queries. +Read more about setting up Log alerts [here](https://docs.microsoft.com/en-in/azure/azure-monitor/platform/alerts-log). -**Step-1: Optional** (Ops Team) Add Alert Management Solution Pack from OMS Solution Gallery (choose default installation) in the OMS subscription. - -![05_Setting_OMS_Workspace_Solution_Gallery](../Images/05_Setting_OMS_Workspace_Solution_Gallery.PNG) -![05_Setting_OMS_Workspace_Alert_Management](../Images/05_Setting_OMS_Workspace_Alert_Management.PNG) - -**Step-2: Optional** (Ops Team) Add Activity Log Analytics Solution Pack from the gallery (see pic above) -and configure it (steps below). After you install the Activity Log Solution Pack from the gallery, -it's dashboard tile directs you to do connect a log source as shown below: - -![05_Setting_OMS_Workspace_Activity_Log_Analytics](../Images/05_Setting_OMS_Workspace_Activity_Log_Analytics.PNG) +**Step-2: Optional** (Ops Team) Collect and analyze Azure activity logs in Log Analytics +Below are the steps to connect to a log source: -1. This connection is setup in the OMS subscription by going into the Log Analytics feature and +1. This connection is setup in the Log Analytics subscription by going into the Log Analytics workspace feature and clicking on "Azure Activity Log" in the Workspace Data Sources list as below: -![05_Setting_OMS_Workspace_Azure_Activity_Log](../Images/05_Setting_OMS_Workspace_Azure_Activity_Log.PNG) +![05_Setting_OMS_Workspace_Azure_Activity_Log](../Images/05_Setting_Log_Analytics_Workspace_Azure_Activity_Log.png) -2. From the OMS Subscription, one can view all subscriptions that the Ops team person (current user) -has at least "Reader" level access as options for 'Connecting' to Log Analytics pack. It means that App team -subscriptions will show here as an option only if at least "Reader" access is granted to the -current OMS user. (This is an OMS product requirement.) +2. From the Log Analytics Subscription, one can view all subscriptions that the Ops team person (current user) +has at least "Log Analytics Reader" level access. It means that App team +subscriptions will show here as an option only if at least "Log Analytics Reader" access is granted to the +current Log Analytics user. Choose the subscription(s) corresponding to the apps that are being monitored and click 'Connect'. -![05_Setting_OMS_Workspace_Connecting_Log_Analytics](../Images/05_Setting_OMS_Workspace_Connecting_Log_Analytics.PNG) +![05_Setting_Log_Analytics_Workspace_Connecting_Log_Analytics](../Images/05_Setting_Log_Analytics_Workspace_Connecting_Log_Analytics.png) -> Note: The above steps have to be done from the **OMS** subscription. +> Note: The above steps have to be done from the **Log Analytics** subscription. -At this point, the app subscription is setup to pipe it's Azure Activity Log events to the OMS workspace. +At this point, the app subscription is setup to pipe it's Azure Activity Log events to the Log Analytics workspace. -In the next 2 steps we will configure AzSK to send data to the OMS workspace from a PowerShell session. -This is just so that we can verify that events generated AzSK are getting routed to the OMS workspace +In the next steps we will configure AzSK to send data to the Log Analytics workspace from a PowerShell session. This can be done by running commands discussed in [[B] Testing Log Anaytics workspace connectivity](Readme.md#b-testing-log-anaytics-workspace-connectivity). +This is just so that we can verify that events generated AzSK are getting routed to the Log Analytics workspace correctly. diff --git a/06-Security-Telemetry/App-Insights-Queries/Readme.md b/06-Security-Telemetry/App-Insights-Queries/Readme.md index 336fde35..5b843d7a 100644 --- a/06-Security-Telemetry/App-Insights-Queries/Readme.md +++ b/06-Security-Telemetry/App-Insights-Queries/Readme.md @@ -1,113 +1,202 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + ### Contents - [Overview](#overview) + - [Usage statistics](#usage-statistics) - - [Subscriptions evaluated by AzSK](#subscriptions-evaluated-by-azsk) - - [Resources evaluated by AzSK](#resources-evaluated-by-azsk) - - [AzSK Version statistics](#azsk-version-statistics) + - [Total number of subscriptions evaluated per day](#Total-number-of-Subscriptions-evaluated-per-day) + - [Total number of resources evaluated per day](#Total-number-of-resources-evaluated-per-day) + - [Total number of controls evaluated per day](#Total-number-of-controls-evaluated-per-day) + +- [AzSK Version statistics](#azsk-version-statistics) + - [Org AzSK version vs latest available AzSK version](#Org-AzSK-version-vs-latest-available-AzSK-version) + - [CA AzSK version Summary](#CA-AzSK-version-Summary) + - [SpotCheck AzSK version summary](#SpotCheck-AzSK-version-summary) + - [CICD SVT Task AzSK version summary](#CICD-SVT-Task-AzSK-version-summary) + +- [Continuous Assurance Health Monitoring](#Continuous-Assurance-Health-Monitoring) + - [CA reporting exceptions](#CA-reporting-exceptions) + - [Calculate resources scan time in CA](#Calculate-resources-scan-time-in-CA) + - [Controls statistics](#controls-statistics) - - [Controls scan result distribution on daily basis](#controls-scan-result-distribution-on-daily-basis) + - [Controls status trend](#Controls-status-trend) - [Drift in failing controls](#drift-in-failing-controls) - [Drift in attested controls](#drift-in-attested-controls) - + +- [Resource Inventory](#Resource-Inventory) + - [Resource inventory all over the subscription](#Resource-inventory-all-over-the-subscription) + - [Resource inventory for particular subscription](#Resource-inventory-for-particular-subscription) + - [Virtual Machines OS Type Summary](Virtual-Machines-OS-Type-Summary) + ## Overview -The telemetry data can be leveraged by subscription owners to understand AzSK usage, monitor compliance, troubleshooting etc. using querying capabilities provided by App Insights. +The telemetry data can be leveraged by org policy owners to understand AzSK usage, monitor compliance drift, CA health, resource inventory, troubleshooting etc. ## Usage statistics -### Subscriptions evaluated by AzSK -Below query is useful to get an idea of overall AzSK usage in your subscriptions. It displays number of subscriptions scanned by AzSK (through CA runbook/SpotCheck (Adhoc scan)/VSO task) in last 7 days. +#### _Total number of Subscriptions evaluated per day_ +Get an idea of overall AzSK usage in the org. Query displays unique number of subscriptions scanned by AzSK (through CA runbook/SpotCheck (Adhoc scan)/VSO task) per day over last 7 days period. ``` AIQL customEvents | where timestamp >= ago(7d) | where name == "Control Scanned" -| summarize count() by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.ResourceId) -| summarize ResourceCount = count() by Day, ScanSource +| summarize arg_max(timestamp, *) by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.SubscriptionId) +| summarize SubscriptionCount = count() by Day, ScanSource | render barchart ``` +**Below is the sample graph generated by App Insights for above query.** + +![AIGraph_Usage.PNG](/Images/06_AIGraph_Usage.PNG) -### Resources evaluated by AzSK -Below query is useful to get an idea of overall AzSK usage in your subscriptions. It displays number of resources scanned by AzSK (through CA runbook/SpotCheck (Adhoc scan)/VSO task) in last 7 days. +#### _Total number of resources evaluated per day_ +Number of resources scanned (through CA runbook/SpotCheck (Adhoc scan)/VSO task) per day over last 7 days period. ``` AIQL customEvents | where timestamp >= ago(7d) -| where name == "Control -Scanned" -| summarize count() by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.SubscriptionId), tostring(customDimensions.ResourceId) -| summarize count() by Day, ScanSource +| where name == "Control Scanned" +| summarize arg_max(timestamp, *) by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.ResourceId) +| summarize ResourceCount = count() by Day, ScanSource | render barchart ``` -**Below is the sample graph generated by App Insights for above two queries.** -![AIGraph_Usage.jpg](/Images/06_AIGraph_Usage.jpg) +#### _Total number of controls evaluated per day_ +Number of controls scanned (through CA runbook/SpotCheck (Adhoc scan)/VSO task) per day over last 7 days period. + +``` AIQL +customEvents +| where timestamp >= ago(7d) +| where name == "Control Scanned" +| summarize arg_max(timestamp, *) by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.ResourceId),tostring(customDimensions.ControlId) +| summarize ResourceCount = count() by Day, ScanSource +| render barchart +``` ### AzSK Version statistics -#### _CA AzSK module version usage_ +#### _Org AzSK version vs latest available AzSK version_ -Below query is useful to check AzSK module version used by CA installed in subscriptions. +Get current AzSK version configured in Org vs latest available version. If version differs, consider updating it to latest version ``` AIQL customEvents -| where timestamp >= ago(3d) +| where timestamp > ago(2d) and name == "Control Scanned" +| summarize arg_max(timestamp, *) +| project OrgAzSKVersion=tostring(customDimensions.OrgVersion),LatestAzSKVersion=tostring(tostring(customDimensions.LatestVersion)) +``` + + +#### _CA AzSK version Summary_ + +Display AzSK module version used by CA. This graph plays important role for monitoring CA AzSK auto upgrade scenario when Org policy AzSK version is updated with latest version. CA will pick AzSK version from policy file (AzSK.Pre.json) and start installing/running with it. + +``` AIQL +customEvents +| where timestamp >= ago(7d) | where name == "Control Scanned" | where customDimensions.ScanSource =="Runbook" -| summarize ControlsScanned = count() by Version = tostring(customDimensions.ScannerVersion), SubId = tostring(customDimensions.SubscriptionId) -| distinct Version,SubId,ControlsScanned -| summarize CurrentRunningCAAzSKVersion=count() by Version +| summarize arg_max(timestamp, *) by SubId = tostring(customDimensions.SubscriptionId) +| summarize CurrentRunningCAAzSKVersion= count() by Version = tostring(customDimensions.ScannerVersion) | render piechart ``` -#### _SpotCheck AzSK module version usage_ +#### _SpotCheck AzSK version summary_ -Below query is useful to check AzSK module version used by developers in local scan. +Number of subscriptions scanned with AzSK module version by developers or application teams in local scan. ``` AIQL customEvents | where timestamp >= ago(3d) | where name == "Control Scanned" | where customDimensions.ScanSource =="SpotCheck" -| summarize ControlsScanned = count() by Version = tostring(customDimensions.ScannerVersion), SubId = tostring(customDimensions.SubscriptionId) -| distinct Version,SubId,ControlsScanned -| summarize AzSKVersion=count() by Version +| summarize arg_max(timestamp, *) by Version = tostring(customDimensions.ScannerVersion), SubId = tostring(customDimensions.SubscriptionId) +| summarize SubscripitionScanned=count() by tostring(Version) | render piechart ``` -#### _CA runbook version usage_ +#### _CICD SVT Task AzSK version summary_ -Below query is useful to check CA runbook version in your subscriptions. +Number of subscriptions scanned with AzSK module version by CICD SVT task in VSO. ``` AIQL customEvents -| where timestamp > ago(2d) and name == "Control Scanned" and customDimensions.ScanSource == "Runbook" -| summarize arg_max(timestamp, *) by tostring(customDimensions.SubscriptionId) -| project tostring(customDimensions.SubscriptionId) -| join kind= leftouter -( -customEvents -| where timestamp > ago(2d) and name == "CA Job Started" -| summarize arg_max(timestamp, *) by tostring(customDimensions.SubscriptionId) -| project tostring(customDimensions.SubscriptionId),tostring(customDimensions.AzSKRunbookVersion) -) -on customDimensions_SubscriptionId -| extend RunbookVersion = iff(isempty(customDimensions_AzSKRunbookVersion)==true,"< 2.5.0",customDimensions_AzSKRunbookVersion) -| summarize RunningRunbook=count() by RunbookVersion +| where timestamp >= ago(3d) +| where name == "Control Scanned" +| where customDimensions.ScanSource =="VSO" +| summarize arg_max(timestamp, *) by Version = tostring(customDimensions.ScannerVersion), SubId = tostring(customDimensions.SubscriptionId) +| summarize SubscripitionScanned=count() by tostring(Version) | render piechart ``` -**Below are the sample graphs generated by App Insights for above three queries.** -![AIGraph_ModuleVersion.jpg](/Images/06_AIGraph_ModuleVersion.jpg) +## Continuous Assurance Health Monitoring + +#### _CA reporting exceptions_ -![AIGraph_RunbookVersion.jpg](/Images/06_AIGraph_RunbookVersion.jpg) +Exceptions reporting always does not mean CA is not in healthy state. It may throw exceptions due to multiple reasons like target Sub id not correctly provided in central CA etc. +Most of the issue with CA health can be determined from _Get-AzSKContinuousAssurance_ cmdlet. +``` AIQL +customEvents + | where name contains "Error" and name contains "CA" + | where timestamp > ago(7d) + | summarize count() by name, tostring(customDimensions.SubscriptionId),bin(timestamp,1d) + | summarize count() by name,bin(timestamp, 1d) + | render barchart +``` + +#### _Calculate resources scan time in CA_ + +Calcuate total time taken for subscriptions to scan all resources in CA. + +**Note:** This query gives only subscriptions timings for which scan got completed within single job. + +``` AIQL +// Get the scan identifiers for which all resources scan completed within single CA job +customEvents +| where timestamp > ago(3d) and name == "Command Started" +and customDimensions.Command == "Get-AzSKAzureServicesSecurityStatus" and customDimensions.ScanSource == "Runbook" +| summarize TotalJobsRequiredToCompleteScan= count() by UniqueRunIdentifier = tostring(customDimensions.UniqueRunIdentifier) +| where TotalJobsRequiredToCompleteScan == 1 +| join kind= inner ( + // Get the start time using command started + customEvents + | where timestamp > ago(3d) and name == "Command Started" + and customDimensions.Command == "Get-AzSKAzureServicesSecurityStatus" + and customDimensions.ScanSource == "Runbook" + | summarize arg_max(timestamp, *) by SubId = tostring(customDimensions.SubscriptionId), RunIdentifier = tostring(customDimensions.RunIdentifier) + | join ( + // Get scan completed time + customEvents + | where timestamp > ago(3d) and name == "Command Completed" + and customDimensions.Command == "Get-AzSKAzureServicesSecurityStatus" + and customDimensions.ScanSource == "Runbook" + | summarize arg_max(timestamp, *) by SubId = tostring(customDimensions.SubscriptionId), RunIdentifier= tostring(customDimensions.RunIdentifier) + ) on SubId, RunIdentifier + | extend ScanTimeInMins = datetime_diff('minute',timestamp1,timestamp) + | project SubId, UniqueRunIdentifier = tostring(customDimensions.UniqueRunIdentifier),SubName = tostring(customDimensions.SubscriptionName), ScanTimeInMins +) +// Filter results for only subs for which scan completed within single job using identifier +on UniqueRunIdentifier +| join kind= inner ( + // Get the number of resources scanned for particular run identifier + customEvents + | where timestamp > ago(3d) and name == "Control Scanned" + | summarize arg_max(timestamp, *) by UniqueRunIdentifier = tostring(customDimensions.UniqueRunIdentifier), tostring(customDimensions.ResourceId) + | summarize TotalResourcesScanned = count() by UniqueRunIdentifier +) on UniqueRunIdentifier +| project SubId, SubName, TotalResourcesScanned, ScanTimeInMins + +``` ## Controls statistics -### _Controls scan result distribution on daily basis_ -Below query is useful to get an idea of overall scan happening in all subscriptions. +#### _Controls status trend per day_ ``` AIQL customEvents @@ -119,9 +208,9 @@ customEvents ``` **Below is the sample graph generated by App Insights for above query.** -![AIGraph_ScanResultDistribution.jpg](/Images/06_AIGraph_ScanResultDistribution.jpg) +![AIGraph_ScanResultDistribution.PNG](/Images/06_AIGraph_ScanResultDistribution.PNG) -### _Drift in failing controls_ +#### _Drift in failing controls_ You can monitor the increase/decrease in "Failed" controls in last two days with this query. Positive drift needs your attention. Examine the resources whose controls are showing positive drift. Negative drift shows that controls are being fixed in last two days which is positive sign. @@ -209,4 +298,42 @@ on customDimensions_ControlId,$left.oldresult==$right.newresult **Below are the sample graphs generated by App Insights for above two queries.** -![AIGraph_FailednAttestation_Drift.jpg](/Images/06_AIGraph_FailednAttestation_Drift.jpg) +![AIGraph_FailednAttestation_Drift.PNG](/Images/06_AIGraph_FailednAttestation_Drift.PNG) + + +## Resource Inventory + +#### _Resource inventory all over the subscription_ + +Resource inventory details for subscriptions running CA + +``` AIQL +customEvents +| where timestamp > ago(3d) and name == "Resource Inventory" +| summarize arg_max(timestamp, *) by tostring(customDimensions.ResourceId) +| summarize ResourceCount= count() by ResourceType= tostring(customDimensions.ResourceType) +``` + +#### _Resource inventory for particular subscription_ + +Replace SubscriptionId with value + +``` AIQL +customEvents +| where timestamp > ago(3d) and name == "Resource Inventory" and customDimensions.SubscriptionId ~= "" +| summarize arg_max(timestamp, *) by tostring(customDimensions.ResourceId) +| summarize ResourceCount= count() by ResourceType= tostring(customDimensions.ResourceType) +``` + +#### _Virtual Machines OS Type Summary_ +Get number of Windows vs Linux VM present all over subscriptions + +``` AIQL +customEvents +| where timestamp > ago(3d) and name == "Control Scanned" and customDimensions.ControlId contains "Azure_VirtualMachine_" +| extend VMProperties = parse_json(tostring(customDimensions.ResourceMetadata)) +| extend OSType = VMProperties.VMDetails.OSType +| summarize arg_max(timestamp, *) by tostring(customDimensions.ResourceId) +| summarize count() by tostring(OSType) +``` + diff --git a/06-Security-Telemetry/Readme.md b/06-Security-Telemetry/Readme.md index ec527702..154451b7 100644 --- a/06-Security-Telemetry/Readme.md +++ b/06-Security-Telemetry/Readme.md @@ -1,5 +1,10 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # Security Telemetry -![Security_Telemetry](../Images/Security_Telemetry.PNG) +![Security_Telemetry](../Images/Security_Telemetry.png) @@ -14,15 +19,14 @@ - [App Insights Visualization](#app-insights-visualization) - [Usage Telemetry](#usage-telemetry) - [Enable/Disable Usage Telemetry](#enabledisable-usage-telemetry) -- [FAQs](#faqs) ## Overview The Secure DevOps Kit generates telemetry events from all stages of dev ops. That is, events are generated when an engineer runs a scan ad hoc or when SVTs are run in CICD or subscriptions are scanned via Continuous Assurance (CA). The telemetry can be collected and aggregated across an organization. When combined with other organization metadata (e.g., a mapping of subscriptions to applications or service lines or business groups), this can yield a powerful platform for supporting a data-driven approach cloud risk governance and allow organizations to drive measured and targeted security improvement initiatives in a continuous and incremental fashion (just like the rest of dev ops). The telemetry data from AzSK can be leveraged in two key ways: -- Application Insights based called Control Telemetry (will be renamed to Org Telemetry soon). There are two ways possible. One, configure it centrally, two, configure it specifically in end-user's machine +- Application Insights based � called Control Telemetry (will be renamed to Org Telemetry soon). There are two ways possible. One, configure it centrally, two, configure it specifically in end-user's machine -- API based this is a custom solution using WebAPI and SQL to collect events and enrich it with organizational metadata. This lets an organization track and drive adoption and usage of the AzSK and provides a window into the org's DevSecOps Maturity. API based telemetry will be release in coming months when we release documents for how organization can customize AzSK for their needs +- API based � this is a custom solution using WebAPI and SQL to collect events and enrich it with organizational metadata. This lets an organization track and drive adoption and usage of the AzSK and provides a window into the org's DevSecOps Maturity. API based telemetry will be release in coming months when we release documents for how organization can customize AzSK for their needs [Back to top...](#contents) @@ -40,9 +44,9 @@ The setup is done once by a central security team or monitoring team. No action An Application Insights account is required to collect the data. Create an Application Insights account in Azure with the Application Type 'General' and take a note of the Instrumentation Key from the Overview section of the resource. -![Setup_Create_App_Insights](/Images/06_Setup_Create_App_Insights.jpg) +![Setup_Create_App_Insights](/Images/06_Setup_Create_App_Insights.PNG) -![Setup_Locate_AI_Instrumentation_Key](/Images/06_Setup_Locate_AI_Instrumentation_Key.jpg) +![Setup_Locate_AI_Instrumentation_Key](/Images/06_Setup_Locate_AI_Instrumentation_Key.PNG) With this you can refer [local control telemetry](#local-control-telemetry) section for further steps. @@ -57,7 +61,7 @@ Coming soon The team that created the instrumentation key (in [section](#application-insights)) can share the key with the below command for the application development teams to use it. It is preferred to have this step as part of on-boarding. ``` PowerShell -Set-AzSKLocalControlTelemetrySettings -LocalControlTelemetryKey '' -EnableLocalControlTelemetry $true +Set-AzSKLocalAIOrgTelemetrySettings -LocalAIOrgTelemetryKey '' -EnableLocalAIOrgTelemetry $true ``` The command configures the AzSK toolkit to send data to the given Applications Insights account from user's machine. @@ -68,7 +72,7 @@ The command configures the AzSK toolkit to send data to the given Applications I To check that events are flowing into Application Insights, after setting the local telemetry key execute a subscription security command. Normally it will take around 4 to 5 minutes for the data to appear in App Insights. In Azure portal, navigate to App Insights resource 'Overview' -> Search and select an event listed with name **Control Scanned**. -![Understand_Locate_AI_Data](/Images/06_Understand_Locate_AI_Data.jpg) +![Understand_Locate_AI_Data](/Images/06_Understand_Locate_AI_Data.PNG) #### Event Data Properties @@ -120,11 +124,11 @@ Option 1 is straight forward. For more information on it, check the [link](https Option 2 gives the flexibility of querying and visualizing. To start click on the Analytics link on the App Insights resource overview. This will launch a new site. -![Locate_Analytics_Link](/Images/06_Locate_Analytics_Link.jpg) +![Locate_Analytics_Link](/Images/06_Locate_Analytics_Link.PNG) After the site is loaded, click on the new tab option to start writing queries. -![Locate_Analytics_New_Query](/Images/06_Locate_Analytics_New_Query.jpg) +![Locate_Analytics_New_Query](/Images/06_Locate_Analytics_New_Query.PNG) Run the following query @@ -137,7 +141,7 @@ customEvents There is a filter in the top right, which gives the easy option to select time ranges. This can be done via code as well. -![Run_Analytics_Query](/Images/06_Run_Analytics_Query.jpg) +![Run_Analytics_Query](/Images/06_Run_Analytics_Query.PNG) The query computes top failing 10 Azure features that are scanned by the toolkit. @@ -216,4 +220,4 @@ Set-AzSKUsageTelemetryLevel -Level None Set-AzSKUsageTelemetryLevel -Level Anonymous ``` -[Back to top...](#contents) \ No newline at end of file +[Back to top...](#contents) diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.json b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.json new file mode 100644 index 00000000..d395c405 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.json @@ -0,0 +1,24 @@ +{ + "FeatureName": "AppInsights", + "Reference": "aka.ms/azsktcp/appinsights", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_AppInsights_No_Limited_Basic_Plan", + "Description": "Do not use ‘Limited Basic' tier plan for enterprise apps.", + "Id": "AppInsights1001", + "ControlSeverity": "Medium", + "Automated": "Yes", + "MethodName": "CheckAIPricingPlan", + "Recommendation": "Use an enterprise grade pricing plan other than ‘Limited Basic’.", + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "AppInsights" + ], + "Enabled": true, + "Rationale": "Logical intention for the extended control" + } + ] +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.ps1 new file mode 100644 index 00000000..9927d3b6 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ext.ps1 @@ -0,0 +1,28 @@ +Set-StrictMode -Version Latest + +# Class name must have Ext suffix. Class must be inherited from Feature class +class AppInsightsExt: AppInsights +{ + AppInsightsExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + $this.GetResourceObject(); + } + + hidden [ControlResult] CheckAIPricingPlan([ControlResult] $controlResult) + { + # Your function logic goes here. + Write-Host("Checking AI pricing plan...") + $ai = $this.ResourceObject + if ($ai.PricingPlan -eq 'Limited Basic') + { + $controlResult.VerificationResult = [VerificationResult]::Failed + $controlResult.AddMessage("AI: Use an enterprise grade pricing plan other than ‘Limited Basic’"); + } + else { + $controlResult.VerificationResult = [VerificationResult]::Passed + $controlResult.AddMessage("AI: Non-basic plan is used per expectation!"); + } + return $controlResult; + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.json b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.json new file mode 100644 index 00000000..9fdc10f3 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.json @@ -0,0 +1,6 @@ +{ + "FeatureName": "AppInsights", + "Reference": "aka.ms/azsktcp/appinsights", + "IsMaintenanceMode": false, + "Controls": [] +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ps1 new file mode 100644 index 00000000..68501756 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/AppInsights.ps1 @@ -0,0 +1,28 @@ +Set-StrictMode -Version Latest +class AppInsights: AzSVTBase +{ + hidden [PSObject] $ResourceObject; + + AppInsights([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + $this.GetResourceObject(); + } + + hidden [PSObject] GetResourceObject() + { + if (-not $this.ResourceObject) + { + # Get resource details from AzureRm + $this.ResourceObject = Get-AzureRmApplicationInsights -Name $this.ResourceContext.ResourceName -ResourceGroupName $this.ResourceContext.ResourceGroupName -Full + + if(-not $this.ResourceObject) + { + throw ([SuppressedException]::new(("Resource '$($this.ResourceContext.ResourceName)' not found under Resource Group '$($this.ResourceContext.ResourceGroupName)'"), [SuppressedExceptionType]::InvalidOperation)) + } + + } + + return $this.ResourceObject; + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.json b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.json new file mode 100644 index 00000000..6cb1bc26 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.json @@ -0,0 +1,24 @@ +{ + "FeatureName": "Feature", + "Reference": "aka.ms/azsktcp/feature", // This value should be same as original Feature.json + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Feature_Functionality", // Define the new control id + "Description": "Latest TLS version should be used", // Description for your control + "Id": "Feature1001", // Ensure that all the internal ids are appended with 4 digit integer code + "ControlSeverity": "Medium", // Control the severity + "Automated": "Yes", // Control the automation status + "MethodName": "FunctionToExtend", // Update the method name with the new one provided above + "Recommendation": "Steps to fix the extended control", + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "Feature" // Feature specific required Tag (if any) + ], + "Enabled": true, + "Rationale": "Logical intention for the extended control" + } + ] +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.ps1 new file mode 100644 index 00000000..68fe067d --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Feature.ext.ps1 @@ -0,0 +1,18 @@ +Set-StrictMode -Version Latest + +# Class name must have Ext suffix. Class must be inherited from Feature class +class FeatureExt: Feature +{ + FeatureExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + $this.GetResourceObject(); + } + + + hidden [ControlResult] FunctionToExtend([ControlResult] $controlResult) + { + # Your function logic goes here. + return $controlResult; + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/ListenerName.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/ListenerName.ext.ps1 new file mode 100644 index 00000000..86599339 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/ListenerName.ext.ps1 @@ -0,0 +1,249 @@ +Set-StrictMode -Version Latest + +# Listener class name must have Ext suffix +# Listener class must be inherited from ListenerBase +class ListenerNameExt: ListenerBase +{ + + # default constructor + hidden ListenerNameExt() + { + } + + hidden static [ListenerNameExt] $Instance = $null; + + # Create instance of class + static [ListenerNameExt] GetInstance() + { + if ( $null -eq [ListenerNameExt]::Instance) + { + [ListenerNameExt]::Instance = [ListenerNameExt]::new(); + } + return [ListenerNameExt]::Instance + } + + [void] RegisterEvents() + { + + $this.UnregisterEvents(); + + # Below event will be triggered only once per execution when the run identifier is generated. The run identifier is unique for each scan. + $this.RegisterEvent([AzSKRootEvent]::GenerateRunIdentifier, { + $currentInstance = [ListenerNameExt]::GetInstance(); + try + { + $runIdentifier = [AzSKRootEventArgument] ($Event.SourceArgs | Select-Object -First 1) + $currentInstance.SetRunIdentifier($runIdentifier); + } + catch + { + $currentInstance.PublishException($_); + } + }); + + + # uncomment below code if the listener should handle CommandStarted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::CommandStarted, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle CommandCompleted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::CommandCompleted, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle CommandError event of SVTEvent + # $this.RegisterEvent([SVTEvent]::CommandError, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # } + # }); + + + # uncomment below code if the listener should handle EvaluationStarted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::EvaluationStarted, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle EvaluationCompleted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::EvaluationCompleted, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle EvaluationError event of SVTEvent + # $this.RegisterEvent([SVTEvent]::EvaluationError, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # } + # }); + + + # uncomment below code if the listener should handle ControlStarted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::ControlStarted, { + # $currentInstance = [WriteDetailedLog]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle ControlCompleted event of SVTEvent + # $this.RegisterEvent([SVTEvent]::ControlCompleted, { + # $currentInstance = [WriteDetailedLog]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle ControlError event of SVTEvent + # $this.RegisterEvent([SVTEvent]::ControlError, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # } + # }); + + + # uncomment below code if the listener should handle CommandProcessing event of AzSKRootEvent + # $this.RegisterEvent([AzSKRootEvent]::CommandProcessing, { + # $currentInstance = [WriteDetailedLog]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle PublishCustomData event of AzSKRootEvent + # $this.RegisterEvent([AzSKRootEvent]::PublishCustomData, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle Exception event of AzSKGenericEvent + # $this.RegisterEvent([AzSKGenericEvent]::Exception, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # } + # }); + + + # uncomment below code if the listener should handle CommandError event of AzSKRootEvent + # $this.RegisterEvent([AzSKRootEvent]::CommandError, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # } + # }); + + + # uncomment below code if the listener should handle UnsupportedResources event of AzSKRootEvent + # $this.RegisterEvent([AzSKRootEvent]::UnsupportedResources, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + + # uncomment below code if the listener should handle WriteCSV event of AzSKRootEvent + # $this.RegisterEvent([AzSKRootEvent]::WriteCSV, { + # $currentInstance = [ListenerNameExt]::GetInstance(); + # try + # { + + # } + # catch + # { + # $currentInstance.PublishException($_); + # } + # }); + + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Readme.md b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Readme.md new file mode 100644 index 00000000..08d6b477 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Readme.md @@ -0,0 +1,550 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](/ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# Extending AzSK Modules + +## Contents +- [Structure](Readme.md#structure) +- [Know more about SVTs](Readme.md#know-more-about-svts) +- [Block diagram to represent the extension model](Readme.md#block-diagram-to-represent-the-extension-model) +- [Steps to extend the control SVT](Readme.md#steps-to-extend-the-control-svt) +- [Steps to override the logic of existing SVT](Readme.md#steps-to-override-the-logic-of-existing-svt) +- [Steps to add extended control in baseline control list](Readme.md#steps-to-add-extended-control-in-baseline-control-list) +- [Steps to debug the extended control while developement](Readme.md#steps-to-debug-the-extended-control-while-development) +- [Steps to add a new SVT to the AzSK module](Readme.md#steps-to-add-a-new-SVT-to-the-AzSK-module) +- [FAQ](Readme.md#faqs) +- [References](Readme.md#references) + +---------------------------------------------- +### Structure + +Before we get started with extending the toolkit, it is important to understand the structure of the PowerShell module. Below represents the tree structure of DevOpsKit PS module, out of which you can currently extend SVT (subscription & services) and Listeners only. SVT stands for Security Verification Tests, which constitute different Azure security controls that are scanned by the DevOps Kit. Listeners are like subscribers for control evaluation results. You can route the control results data to data source choice of yours. + + + + ├───AlertMonitoring + ├───ARMChecker + ├───ARMCheckerLib + ├───AzSKInfo + ├───ContinuousAssurance + ├───Framework + │ ├───Abstracts + │ │ └───FixControl + │ ├───Configurations + │ │ ├───AlertMonitoring + │ │ ├───ARMChecker + │ │ ├───AutoUpdate + │ │ ├───AzSKInfo + │ │ ├───ContinuousAssurance + │ │ ├───Migration + │ │ ├───PolicySetup + │ │ ├───SubscriptionSecurity + │ │ └───SVT + │ │ ├───AzSKCfg + │ │ ├───Services + │ │ └───SubscriptionCore + │ ├───Core + │ │ ├───ARMChecker + │ │ ├───AzSKInfo + │ │ ├───AzureMonitoring + │ │ ├───ContinuousAssurance + │ │ ├───FixControl + │ │ │ └───Services + │ │ ├───PolicySetup + │ │ ├───SubscriptionSecurity + │ │ └───SVT + │ │ ├───AzSKCfg + │ │ ├───Services + │ │ └───SubscriptionCore + │ ├───Helpers + │ ├───Listeners + │ │ ├───CA + │ │ ├───EventHub + │ │ ├───FixControl + │ │ │ └───FixControlScripts + │ │ ├───GenericListener + │ │ ├───LogAnalytics + │ │ ├───RemoteReports + │ │ ├───UserReports + │ │ └───Webhook + │ ├───Managers + │ └───Models + │ ├───Common + │ ├───ContinuousAssurance + │ ├───Exception + │ ├───FixControl + │ ├───RemoteReports + │ ├───SubscriptionCore + │ ├───SubscriptionSecurity + │ └───SVT + ├───PolicySetup + ├───SubscriptionSecurity + └───SVT + + +### Know more about SVTs: + + +All our SVTs inherit from a base class called AzSVTBase which will take care of all the required plumbing from the control evaluation code. Every SVT will have a corresponding feature json file under the configurations folder. For example, Storage.ps1 (in the core folder) has a corresponding Storage.json file under configurations folder. These SVTs json have a bunch of configuration parameters, that can be controlled by a policy owner, for instance, you can change the recommendation, modify the description of the control suiting your org, change the severity, etc. + +Below is the typical schema for each control inside the feature json + ``` +{ + "ControlID": "Azure_Subscription_AuthZ_Limit_Admin_Count", //Human friendly control Id. The format used is Azure___ + "Description": "Minimize the number of admins/owners", //Description for the control, which is rendered in all the reports it generates (CSV, AI telemetry, emails etc.). + "Id": "SubscriptionCore1100", //This is internal ID and should be unique. Since the ControlID can be modified, this internal ID ensures that we have a unique link to all the control results evaluation. + "ControlSeverity": "Medium", //Represents the severity of the Control. + "Automated": "Yes", //Indicates whether the given control is Manual/Automated. + "MethodName": "CheckSubscriptionAdminCount", // Represents the Control method that is responsible to evaluate this control. It should be present inside the feature SVT associated with this control. + "Recommendation": "There are 2 steps involved. You need to clean up (1) unexpected 'Classic Administrators'and (2) unexpected 'Owners' on the subscription. (1) Steps to clean up classic administrators (a) Go to https://manage.windowsazure.com/ --> settings tab -> administrators --> select and remove unwanted administrators using remove icon on the bottom ribbon (2) To remove unwanted members from the Owners group simply run the command 'Remove-AzRoleAssignment -SignInName '{signInName}' -Scope '/subscriptions/{subscriptionid}' -RoleDefinitionName Owner'.", //Recommendation typically provides the precise instructions on how to fix this control. + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "AuthZ" + ], // You can decorate your control with different set of tags, that can be used as filters in scan commands. + "Enabled": true , //Defines whether the control is enabled or not. +    "Rationale": "Each additional person in the Owner/Contributor role increases the attack surface for the entire subscription. The number of members in these roles should be kept to as low as possible." //Provides the intent of this control. +} + ``` + +After schema of the control json, let us look at the corresponding feature SVT PS1. + +```PowerShell +#using namespace Microsoft.Azure.Commands.Search.Models +Set-StrictMode -Version Latest +class SubscriptionCore: AzSVTBase +{ + hidden [AzureSecurityCenter] $ASCSettings + hidden [ManagementCertificate[]] $ManagementCertificates + . + . + . + hidden [string[]] $SubscriptionMandatoryTags = @() + + SubscriptionCore([string] $subscriptionId): + Base($subscriptionId) + { + $this.GetResourceObject(); + } + . + . + . + hidden [ControlResult] CheckSubscriptionAdminCount([ControlResult] $controlResult) + { + + #Step 1: This is where the code logic is placed + #Step 2: ControlResult input to this function, which needs to be updated with the verification Result (Passed/Failed/Verify/Manual/Error) based on the control logic + Messages that you add to ControlResult variable will be displayed in the detailed log automatically. + #Step 3: You can directly access the properties from ControlSettings.json e.g. $this.ControlSettings.NoOfApprovedAdmins. Any property that you add to controlsettings.json will be accessible from your SVT + + + + $controlResult.AddMessage("There are a total of $($SubAdmins.Count) admin/owner accounts in your subscription`r`nOf these, the following $($ClientSubAdmins.Count) admin/owner accounts are not from a central team.", ($ClientSubAdmins | Select-Object DisplayName,SignInName,ObjectType, ObjectId)); + + if(($ApprovedSubAdmins | Measure-Object).Count -gt 0) + { + $controlResult.AddMessage("The following $($ApprovedSubAdmins.Count) admin/owner (approved) accounts are from a central team:`r`n", ($ApprovedSubAdmins | Select-Object DisplayName, SignInName, ObjectType, ObjectId)); + } + $controlResult.AddMessage("Note: Approved central team accounts don't count against your limit"); + + if($ClientSubAdmins.Count -gt $this.ControlSettings.NoOfApprovedAdmins) + { + $controlResult.VerificationResult = [VerificationResult]::Failed + $controlResult.AddMessage("Number of admins/owners configured at subscription scope are more than the approved limit: $($this.ControlSettings.NoOfApprovedAdmins). Total: " + $ClientSubAdmins.Count); + } + else { + $controlResult.AddMessage([VerificationResult]::Passed, + "Number of admins/owners configured at subscription scope are with in approved limit: $($this.ControlSettings.NoOfApprovedAdmins). Total: " + $ClientSubAdmins.Count); + } + + return $controlResult; + } + . + . + . +} +``` + +### Block diagram to represent the extension model: +![Block diagram of AzSK extension](../../Images/08_Block_Diagram_AzSK_Extension.png) + + +### Steps to extend the control SVT: +##### A. Extending a GSS SVT +1. Copy the SVT ps1 script that you want to extend and rename the file by replacing ".ps1" with ".ext.ps1". + For example, if you want to extend SubscriptionCore.ps1, copy the file and rename it to SubscriptionCore.ext.ps1. + +2. You need to rename the class, inherit from the core feature class, and then update the constructor to reflect the new name as shown below: + + > e.g. class SubscriptionCore : AzSVTBase => SubscriptionCoreExt : SubscriptionCore + + ```PowerShell + Set-StrictMode -Version Latest + class SubscriptionCoreExt: SubscriptionCore + { + SubscriptionCoreExt([string] $subscriptionId): Base($subscriptionId) + {        +      + } + } + ``` + All the other functions from the class file should be removed. + +3. If you are modifying the logic for a specific control, then retain the required function; or if you are adding a new control, copy any control function from the base class to the extension class reference. + > Note: For a given control in json, the corresponding PowerShell function is provided as value under MethodName property. You can search for that method under the PS script. For eg. In the below case let us assume you want to add a new control that fails if you have more than 2 co-admins. + + ```PowerShell + Set-StrictMode -Version Latest + class SubscriptionCoreExt: SubscriptionCore + { + SubscriptionCoreExt([string] $subscriptionId): + Base($subscriptionId) + {        +      + } + hidden [ControlResult] CheckSubscriptionAdminCountExtension([ControlResult] $controlResult) + { + #This is internal + $scope = $this.SubscriptionContext.Scope; + $RoleAssignments = Get-AzRoleAssignment -Scope $scope -IncludeClassicAdministrators + #Excessive number of admins (> 2) + $SubAdmins = @(); + $SubAdmins += $RoleAssignments | Where-Object { ($_.RoleDefinitionName -eq 'CoAdministrator' -or $_.RoleDefinitionName -like '*ServiceAdministrator*') -and $_.Scope -eq $scope} + if(($SubAdmins| Measure-Object).Count -gt 2) + { + $controlResult.VerificationResult = [VerificationResult]::Failed + $controlResult.AddMessage("Number of admins/owners configured at subscription scope are more than the approved limit: 2. Total: " + $SubAdmins.Count); + } + else { + $controlResult.AddMessage([VerificationResult]::Passed, + "Number of admins/owners configured at subscription scope are with in approved limit: 2. Total: " + $SubAdmins.Count); + } + return $controlResult; + } + } + ``` + + 4. Now you need to prepare the json for the above new control. You can get started by copying the default base json, rename it to .ext.json. In this case you need to rename it as SubscriptionCore.ext.json. Remove all the other controls except for one and update it with new control details. See additional instructions as '//comments' on each line in the example JSON below. Note: Remove the comments from JSON if you happen to use the below as-is. + + > IMPT: Do *not* tag 'Ext' to the 'FeatureName' here. Make sure you have updated the MethodName to the new method name. + > Note: Remove the comments in the below JSON before saving the file + +``` + { + "FeatureName": "SubscriptionCore", + "Reference": "aka.ms/azsktcp/sshealth", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Subscription_AuthZ_Limit_Admin_Count_Ext", //define the new control id + "Description": "Minimize the number of admins", //Description for your control + "Id": "SubscriptionCore1100", //Ensure that all the internal ids are appended with 4 digit integer code + "ControlSeverity": "Medium", //Control the severity + "Automated": "Yes", // Control the automation status + "MethodName": "CheckSubscriptionAdminCountExtension", //Update the method name with the new one provided above + "Recommendation": "There are 2 steps involved. You need to clean up unexpected 'Classic Administrators'. Steps to clean up classic administrators: Go to https://manage.windowsazure.com/ --> settings tab -> administrators --> select and remove unwanted administrators using remove icon on the bottom ribbon.", + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "AuthZ" + ], + "Enabled": true, + "Rationale": "Each additional person in the Owner/Contributor role increases the attack surface for the entire subscription. The number of members in these roles should be kept to as low as possible." + } + ] + } +``` +5. Now upload these files to your policy storage container under base schema version folder (currently 3.1803.0) like any other org policy and add an entry to ServerConfigMetadata.json as shown below: +``` + { + "Name": "SubscriptionCore.ext.json" + }, + { + "Name": "SubscriptionCore.ext.ps1" + } +``` + Refer the below screenshot. + ![Block diagram of AzSK extension](../../Images/08_AzSK_Extension_SVT_Storage_Policy_Example.png) + +6. That's it!! You can now scan the new extended control like any other control. + +```PowerShell + Get-AzSKSubscriptionSecurityStatus -SubscriptionId '' -ControlIds 'Azure_Subscription_AuthZ_Limit_Admin_Count_Ext' +``` + +##### B. Extending a GRS SVT + +We will add a mock control that 'storage accounts must be created in 'eastus2' region. + +1) Get preview policy downloaded to local folder: + + ```Powershell + gop -SubscriptionId -OrgName -DepartmentName -PolicyFolderPath -DownloadPolicy + ``` + +2) Copy Storage.ps1 from module folder -> \Storage.ext.ps1 + + a) Clean up all but constructor, change to StorageExt, base-class to Storage, remove any class members. + + b) Add method that will implement the new control + (see example file attached) + + +3) Copy Storage.json from module folder -> \Storage.ext.json + + a) Remove all, except one existing control (to edit into new control JSON) + + b) Edit the one control to reflect desired control-id, description, etc. + + + Few important things: + + i) ControlId and Id should not conflict with existing ones + + ii) MethodName should correctly reflect the new method you wrote in Storage.ext.ps1 above + + iii) Do not change 'Storage' to 'StorageExt' inside the JSON (at the root node) + +4) Update org policy... (Important: you don't need to edit anything else or manually tweak policy in the blob)! + + ```Powershell + uop -SubscriptionId -OrgName -DepartmentName -PolicyFolderPath + ``` + + +Important: Also note that the "ext" in the file-names above is in all lower-case! + +=============================================================== + +Verifying that the added control works: + +1) Put your local AzSK into the target policy mode... (run "iwr" that is echoed by Step-4 above). + + +2) Run grs for a storage accounts and verify that the control is getting scanned: + grs -s -rgns -rtn Storage + +3) Run specific control-id, and across a couple of storage accounts in diff regions (the AzSKRG one will pass 'eastus2' check): + +```Powershell + grs -s -ResourceGroupNames 'AzSKRG, , ' -ResourceTypeName Storage -ControlIds 'Azure_Storage_Create_In_Approved_Regions' +``` + +### Steps to override the logic of existing SVT: + +1. Add new Feature.ext.ps1/SubscriptionCore.ext.ps1 file with the new function that needs to be executed as per the above documentation. +2. Customize Feature.json file as per https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Readme.md#d-customizing-specific-controls-for-a-service by overriding "MethodName" property value with the new function name that needs to be executed. +3. That's it!! You can now scan the older control with overridden functionality. + +### Steps to add extended control in baseline control list: + +1. Add new control to Feature.ext.json/SubscriptionCore.ext.json file as per the above documentation. +2. Add the new ControlId in baseline control list as per https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Readme.md#c-creating-a-custom-control-baseline-for-your-org +3. That's it!! The newly added control will be scanned while passing "-UseBaselineControls" switch to GSS/GRS cmdlets. + +### Steps to debug the extended control while development: + +Extended Feature.ext.ps1 files are downloaded at C:\Users\\AppData\Local\Microsoft\AzSK\Extensions folder in the execution machine. While debugging, breakpoints need be inserted in those files. + +### Steps to add a new SVT to the AzSK module: + +The following instructions will help you develop SVT for a new Azure service from scratch. That is, using these steps you can add an SVT for an Azure service that is not currently supported in DevOps Kit. + +For illustration purpose, we will be developing SVT for Application Insights (as Application Insights is a resource type not currently supported in the DevOps kit.) + +>**Note:** Currently, adding a completely new SVT to AzSK requires collaboration with the DevOps Kit team. This is because we need to make some changes in the core module to support the new SVT. Please email azsksup@microsoft.com to initiate a discussion. Typically, we will be able to turn such requests around within our monthly sprint. + +> However, while that process is under way, you can still make progress on this task and, in fact, have a completely functioning new SVT created and tested within your org. Only thing is that you may need to do some renaming/minor file updates after the base support is included by the DevOps Kit team in the AzSK code (after which you can deploy for all users in your org for SDL/CICD/usage). + +>In the steps below, those marked '###' are the steps that you have to do when writing your own new SVT for the first time. However, after you communicate the requirement to the AzSK team, we will include changes corresponding to those steps in the official module for future sprints. Subsequently, you will only need to maintain the code corresponding to the remaining steps. + +The steps below follow roundabout the same model as in section [Extending AzSK Module](Readme.md#block-diagram-to-represent-the-extension-model). All controls you implement for the new SVT will be treated as ‘extended’ controls of a blank core SVT. + +1. [###] Create files AppInsights.json and AppInsights.ps1 to represent base classes/control placeholders in the core module. + + Basically these files will serve the purpose of the (within-module) base class for AppInsights SVT and the controls you will write will go into the SVT extension. + + a. Save AppInsights.json (content below) to \AzSK\\Framework\Configurations\SVT\Services. + + AppInsights.json + + ```PowerShell + { + "FeatureName": "AppInsights", + "Reference": "aka.ms/azsktcp/appinsights", + "IsMaintenanceMode": false, + "Controls": [] + } + ``` + + b. Save AppInsights.ps1 (content below) to \AzSK\\Framework\Core\SVT\Services. + + AppInsights.ps1 + + ``` PowerShell + Set-StrictMode -Version Latest + class AppInsights: AzSVTBase + { + hidden [PSObject] $ResourceObject; + + AppInsights([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + $this.GetResourceObject(); + } + + hidden [PSObject] GetResourceObject() + { + if (-not $this.ResourceObject) + { + # Get resource details from AzureRm + $this.ResourceObject = Get-AzureRmApplicationInsights -Name $this.ResourceContext.ResourceName -ResourceGroupName $this.ResourceContext.ResourceGroupName -Full + + if(-not $this.ResourceObject) + { + throw ([SuppressedException]::new(("Resource '$($this.ResourceContext.ResourceName)' not found under Resource Group '$($this.ResourceContext.ResourceGroupName)'"), [SuppressedExceptionType]::InvalidOperation)) + } + + } + + return $this.ResourceObject; + } + } + ``` + + Note that the content/structure of these files is similar to the other SVT base class files (e.g., Batch.json/Batch.ps1). Only that these are hollow classes (i.e., they do not have any controls implemented.) + +2. Create AppInsights.ext.json and AppInsights.ext.ps1 (using the content below) wherever you store AzSK extension code in your source tree. + + Also copy these files to the (local) org policy folder (e.g., %userprofile%\Desktop\ContosoPolicies). + + Note that below we have implemented a single dummy control for App Insights called ‘Azure_AppInsights_No_Limited_Basic_Plan’ (which merely checks and fails if the pricing plan is ‘Limited Basic’). + + AppInsights.ext.json + + ```PowerShell + { + "FeatureName": "AppInsights", + "Reference": "aka.ms/azsktcp/appinsights", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_AppInsights_No_Limited_Basic_Plan", + "Description": "Do not use ‘Limited Basic' tier plan for enterprise apps.", + "Id": "AppInsights1001", + "ControlSeverity": "Medium", + "Automated": "Yes", + "MethodName": "CheckAIPricingPlan", + "Recommendation": "Use an enterprise grade pricing plan other than ‘Limited Basic’.", + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "AppInsights" + ], + "Enabled": true, + "Rationale": "Logical intention for the extended control" + } + ] + } + ``` + + AppInsights.ext.ps1 + + ``` PowerShell + Set-StrictMode -Version Latest + + # Class name must have Ext suffix. Class must be inherited from Feature class + class AppInsightsExt: AppInsights + { + AppInsightsExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + $this.GetResourceObject(); + } + + hidden [ControlResult] CheckAIPricingPlan([ControlResult] $controlResult) + { + # Your function logic goes here. + Write-Host("Checking AI pricing plan...") + $ai = $this.ResourceObject + if ($ai.PricingPlan -eq 'Limited Basic') + { + $controlResult.VerificationResult = [VerificationResult]::Failed + $controlResult.AddMessage("AI: Use an enterprise grade pricing plan other than ‘Limited Basic’"); + } + else { + $controlResult.VerificationResult = [VerificationResult]::Passed + $controlResult.AddMessage("AI: Non-basic plan is used per expectation!"); + } + return $controlResult; + } + } + ``` + +3. Now push the extension files to the org policy server using the command below: + + ``` PowerShell + Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "%userprofile%\Desktop\ContosoPolicies" + ``` + +4. [###] Edit AllResourceTypes.json (\AzSK\\Framework\Configurations\SVT\) in the local module by adding an entry for the Application Insights resource type at the end (note the comma). + + Basically, this is where AzSK looks in the core module code to determine if a resource type is supported or not. + + ``` PowerShell + , + "Microsoft.Insights/Components" + ] + ``` + >**Note:** To determine the exact name for a resource type you are trying to implement an SVT for, you can use the following commands (shown here for Application Insights): + + ```PowerShell + # List all RPs/registration state: + Get-AzureRmResourceProvider -ListAvailable | Select-Object ProviderNamespace, RegistrationState + + # microsoft.insights + (Get-AzureRmResourceProvider -ProviderNamespace microsoft.insights).ResourceTypes.ResourceTypeName + ``` +5. [###] Edit SVTMapping.ps1 (\AzSK\\Framework\Helpers) to add a resource type mapping entry for Application Insights. + + This mapping is how AzSK determines which PowerShell class implements the controls for the resource type. + + ```PowerShell + [ResourceTypeMapping]@{ + ResourceType = "Microsoft.Insights/Components"; + ClassName = "AppInsights"; + JsonFileName = "AppInsights.json"; + ResourceTypeName = "AppInsights"; + }, + ``` +6. (In a fresh PS session) Run the following scan command to evaluate the control: + + ```PowerShell + Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ResourceTypeName AppInsights + #or + Get-AzSKAzureServicesSecurityStatus -SubscriptionId -ResourceGroupNames -ResourceNames + ``` +### FAQs: + +#### I have added ext control in Storage/AppService/VirtualMachine feature as per documentation. My control is still not getting executed. The control is not even coming as Manual in the csv. +Controls in the services like Storage/AppService/VirtualMachine must have some required "Tags" in the feature.ext.json. While initialization of the feature, calculation of applicable control should be done based on those Tags. If the tags are not present in the control, it will be filtered out and will not be executed. Below are some examples of the Tags which are required for the specific features. + **Storage**: Either "StandardSku" or "PremiumSku"/ or both should be added based on application of the ext control + **AppService**: Either "AppService" or "FunctionApp" / or both should be added based on application of the ext control + **VirtualMachine**: Either "Windows" or "Linux" / or both should be added based on application of the ext control + **SQLDatabase**: "SqlDatabase" should be added if control is applicable for SQLDatabase. + For more details about Tag please refer: [Tag details](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#target-specific-controls-during-a-subscription-health-scan) + +### References: +- [SubscriptionCore.ext.json](SubscriptionCore.ext.json) +- [SubscriptionCore.ext.ps1](SubscriptionCore.ext.ps1) +- [Feature.ext.json](Feature.ext.json) +- [Feature.ext.ps1](Feature.ext.ps1) +- [ListenerName.ext.ps1](ListenerName.ext.ps1) diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.json b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.json new file mode 100644 index 00000000..b077e85e --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.json @@ -0,0 +1,29 @@ +{ + "FeatureName": "Storage", + "Reference": "aka.ms/azsktcp/storage", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Storage_Create_In_Approved_Regions", + "Description": "Create storage accounts only in org-approved regions.", + "Id": "AzureStorage910", + "ControlSeverity": "High", + "Automated": "Yes", + "MethodName": "CheckStorageInApprovedRegions", + "Rationale": "We need to create storage accounts in the same region as our customers due to some compliance requirements.", + "Recommendation": "Create a new storage account in the expected region and use Azure copy tools to move the content over. Delete the old storage account after that.", + "Tags": [ + "SDL", + "TCP", + "Automated", + "StandardSku", + "PremiumSku", + "GeneralPurposeStorage", + "BlobStorage", + "HNSDisabled", + "ResourceLocked" + ], + "Enabled": true + } + ] +} diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.ps1 new file mode 100644 index 00000000..add8801f --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/Storage.ext.ps1 @@ -0,0 +1,35 @@ +using namespace Microsoft.Azure.Management.Storage.Models +using namespace Microsoft.WindowsAzure.Storage.Shared.Protocol +Set-StrictMode -Version Latest +class StorageExt: Storage +{ + + StorageExt([string] $subscriptionId, [string] $resourceGroupName, [string] $resourceName): + Base($subscriptionId, $resourceGroupName, $resourceName) + { + } + + StorageExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + } + + + hidden [ControlResult] CheckStorageInApprovedRegions([ControlResult] $controlResult) + { + + if($this.ResourceObject.Location -eq 'eastus2') + { + + $controlResult.VerificationResult = [VerificationResult]::Passed + } + else + { + $controlResult.EnableFixControl = $true; + $controlResult.VerificationResult = [VerificationResult]::Failed + } + + return $controlResult; + } + +} diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.json b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.json new file mode 100644 index 00000000..83d57e6b --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.json @@ -0,0 +1,24 @@ +{ + "FeatureName": "SubscriptionCore", + "Reference": "aka.ms/azsktcp/sshealth", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Subscription_AuthZ_Limit_Admin_Count_Ext", //define the new control id + "Description": "Minimize the number of admins", //Description for your control + "Id": "SubscriptionCore1100", //Ensure that all the internal ids are appended with 4 digit integer code + "ControlSeverity": "Medium", //Control the severity + "Automated": "Yes", // Control the automation status + "MethodName": "CheckSubscriptionAdminCountExtension", //Update the method name with the new one provided above + "Recommendation": "There are 2 steps involved. You need to clean up unexpected 'Classic Administrators'. Steps to clean up classic administrators: Go to https://manage.windowsazure.com/ --> settings tab -> administrators --> select and remove unwanted administrators using remove icon on the bottom ribbon .", + "Tags": [ + "SDL", + "Best Practice", + "Automated", + "AuthZ" + ], + "Enabled": true, + "Rationale": "Each additional person in the Owner/Contributor role increases the attack surface for the entire subscription. The number of members in these roles should be kept to as low as possible." + } + ] +} diff --git a/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.ps1 new file mode 100644 index 00000000..bfdda9b8 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Extending AzSK Module/SubscriptionCore.ext.ps1 @@ -0,0 +1,17 @@ +Set-StrictMode -Version Latest + +# Class name must be SubscriptionCoreExt. Class must be inherited from SubscriptionCore class +class SubscriptionCoreExt: SubscriptionCore +{ + SubscriptionCoreExt([string] $subscriptionId): + Base($subscriptionId) + {        +      + } + + hidden [ControlResult] CheckSubscriptionAdminCountExtension([ControlResult] $controlResult) + { + # Your function logic goes here. + return $controlResult; + } +} diff --git a/07-Customizing-AzSK-for-your-Org/OrgPolicyHealthCheck.md b/07-Customizing-AzSK-for-your-Org/OrgPolicyHealthCheck.md new file mode 100644 index 00000000..0b40e092 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/OrgPolicyHealthCheck.md @@ -0,0 +1,40 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# AzSK Custom Org Policy Health Check + +### [Overview](OrgPolicyHealthCheck.md#overview-1) + +### [Run Org Policy Health Check](OrgPolicyHealthCheck.md#run-org-policy-health-check-1) + +## Overview + +#### When and why should I check org policy health + +AzSK keeps on adding and enhancing features with different capabilities to monitor Security compliance for Org subscriptions. During these enhancement in new releases, it may include latest features and also some breaking changes. To provide smoother upgrade and avoid policy break, AzSK provides feature for Org policy to run AzSK components with specific version using configuration(mentioned in AzSK.Pre.json). Currently, we have come up with health and fix script which will validate all mandatory resources and latest configurations are in place. +It is recommendated to run health scan before and after updating AzSK version for Org. +Below steps will guide you through steps + + +## Run Org Policy Health Check + + Validate health of Org policy for mandatory configurations and policy schema syntax issues using below command. You can review the failed checks and follow the remedy suggested. + +```PowerShell +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" +``` + +If you have used customized resource names, you can use below parameter sets to run health check + +```PowerShell +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "RGName" ` + -StorageAccountName "PolicyStorageAccountName" +``` +Review failed check and follow remedy suggested to fix issues. + diff --git a/07-Customizing-AzSK-for-your-Org/OrgPolicyUpdate.md b/07-Customizing-AzSK-for-your-Org/OrgPolicyUpdate.md new file mode 100644 index 00000000..ad6b8d2e --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/OrgPolicyUpdate.md @@ -0,0 +1,181 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# Org Policy Updates + +This page will notify updates for Org Policy with different AzSK versions. You need to follow specific instruction/notes before updating Org policy with respective AzSK version if any breaking changes available to base configurations files like policy files schema, CA runbooks changes, etc. For all updates related to AzSK version, you can refer to [release page](https://azsk.azurewebsites.net/ReleaseNotes/LatestReleaseNotes.html) + +To update Org policy with specific AzSK version, you need to run update Org policy command after installing AzSK module (in new PowerShell session). This will update AzSK.Pre.json present on Org policy with respective version. After policy updade, CA will auto-upgrade to latest Org version. If application teams are using older version(or any other version than mentioned in Org Policy), will start getting update warning. + +```PowerShell +# For Basic Setup +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" -OverrideBaseConfig OrgAzSKVersion + +#For custom Resource Group Setup +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "Contoso-IT-RG" ` + -StorageAccountName "contosoitsa" ` + -PolicyFolderPath "D:\ContosoPolicies" -OverrideBaseConfig OrgAzSKVersion +``` +# AzSK v.4.11.0 + +* Added SVT for ‘public IP address’ as a service to optionally treat each public IP address as an individual resource. Org policy admins can enable this behavior by following [these steps](https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org#How-can-we-treat-each-public-IP-address-as-an-individual-resource) + +# AzSK v.4.10.0 + +* Added support for configuring non-AAD identity providers for app service. Refer [here]( +https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org#how-to-configure-non-aad-identity-providers-for-appservice) for more information. +* Fixed an issue in SVT extension framework wherein extended class were not being correctly applied across resources of the same type. + +# AzSK v.4.4.0 + +* Added capabilities to setup AzSK to scan subscriptions across multiple tenants. Instructions are available [here](https://aka.ms/devopskit/crosstenant). + + + +# AzSK v.4.3.0 + +* Ported Org policy cmdlets to PS Core. After this change, users can perform all org policy management operations from OS X/Linux, etc. + +* Validated support for use of a local folder on the client machine (as opposed to a storage-based blob) as the source for org policy at AzSK runtime. + + + +# AzSK v.4.2.0 + +* Removed a check that was prohibiting use of custom-generated SPNs in central-mode CA. + + + +# AzSK v.4.1.0 + +* Support for AzSK-based telemetry (Log Analytics and Application Insights) features in Azure US Government and Azure China. + +* Documentation covering end-to-end org policy scenarios with hands-on code examples will be published in the org policy section this week. + +* Added support for org policy debug mode to extend ARM Checker controls. + + + +# AzSK v.4.0.0 + +* Fixed an issue in Get-AzSKOrganizationPolicyStatus cmdlet where in local debugging mode, extension files weren't getting loaded. + +* Fixed an issue in Get-AzSKOrganizationPolicyStatus cmdlet checks which were failing after fresh installation of org-policy. + +* Improved messages in the org-policy cmdlets (Install, Get & Update- org policy). + +* Introduced DisableOrgPolicyCheckForSession flag in Set-AzSKPolicySettings cmdlet to disable enforcement of org-policy for the current PS session. This helps in situations when an org-policy owner is working with multiple side-by-side policies. + + + +# AzSK v.3.14.0 + +* Install-AzSKContinuousAssurance (ICA) can now be run even without owner permissions at subscription scope. The user who ran ICA must get the actual owners to configure RBAC for the AzSK_SPN on the subscription. + +* Fixed a bug in CA runbook, CA scans were ignoring resource groups (as specified in the resource groups parameter of ICA) and scanning everything in the subscription. + +> **Note:** Update runbook files with latest compatible version +*"Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -OverrideBaseConfig CARunbooks"* If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. + + +# AzSK v.3.14.0 + +* Support for segregating DevOps Kit alerts by mandatory v. optional is now available for all customers. The default cmdlets (Set-AzSKSubscriptionSecurity and Set-AzSKAlerts) will only setup ‘mandatory’ subset of activity alerts. (Please see previous sprint release notes for more.) + +> **Note:** Breaking schema changes are done for alert policy file "Subscription.InsARMAlerts.json". Refer path to get the latest schema and update org policy if this file is customized for the org "%userprofile%\Documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\SubscriptionSecurity\Subscription.InsARMAlerts.json" + + + +# AzSK v.3.13.0 + +* Support for extensibility for ARM Checker. You can now add new controls to existing services and also add altogether new services to be scanned in the ARM Checker for your organization. +* Some of the re-configuration of DevOps Kit alerts by mandatory v. optional will become available in the next sprint. + +No policy schema changes + + +# AzSK v.3.12.0 + +* There is big change from release(3.11.0) related to migration of the DevOps Kit from AzureRM to the new Az-* PowerShell libraries +> **Note:** If you are upgrading from version 3.10.0 or below, you need to follow the below steps +> 1. Org-policy owner should download the latest AzSK module using the command: *"Install-Module AzSK -Scope CurrentUser -AllowClobber -Force +"*. +> 2. Import the latest AzSK module in a fresh PowerShell session and update your org-policy using the command: *"Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -PolicyFolderPath `` -OverrideBaseConfig All"* +> 3. Run the iwr and update the CA by running the *"Update-AzSKContinuousAssurance"* command with the *"-FixModules"* switch. + +* Update all the AzureRM and Azure commands in your SVT extensions to its equivalent in the Az-* module. + +# AzSK v.3.11.0 + +* The big change in this release is the migration of the DevOps Kit from AzureRM to the new Az-* PowerShell libraries +> **Note:** If you are upgrading from version 3.10.0 or below, you need to follow the below steps +> 1. Org-policy owner should download the latest AzSK module using the command: *"Install-Module AzSK -Scope CurrentUser -AllowClobber -Force +"*. +> 2. Import the latest AzSK module in a fresh PowerShell session and update your org-policy using the command: *"Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -PolicyFolderPath `` -OverrideBaseConfig All"* +> 3. Run the iwr and update the CA by running the *"Update-AzSKContinuousAssurance"* command with the *"-FixModules"* switch. + +* Update all the AzureRM and Azure commands in your SVT extensions to its equivalent in the Az-* module. + +# AzSK v.3.9.0 + +* The ARM Checker task in AzSK CICD Extension now respects org policy ' this will let org policy owners customize behavior of the task. (Note that this was possible for the SVT task earlier'only the ARM Checker task was missing the capability.) +* Ability to run CA in sovereign clouds + ability to apply custom org policy for SDL, CICD and CA for such subscriptions. (Please review GitHub docs for the steps needed.) + +# AzSK v.3.8.0 + +* Ability to run manual and CICD scans on sovereign clouds. Please review GitHub docs for the steps needed. +* For central mode CA scanning, if central subscription is used for logging, then CA will not write to target subscription storage account any more. (Earlier, it used still use the target subscription storage account for checkpoints and other metadata.) For new setups or new target subscriptions added to the configuration, DevOps Kit will not create resources (or AzSKRG) in the target subscription. + +# AzSK v.3.7.0 + +> **Note:** If you are upgrading from version 3.5.0 or below. you need to follow below steps +> 1. Update runbook files with latest compatible version +*"Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -OverrideBaseConfig CARunbooks"* If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. +> 2. If Org policy is customized with SecurityCenter configurations. You have to update policy with latest (SecurityCenter.json) schema from 3.7.0. + +No specific updates for Org policy features + +# AzSK v.3.6.1 + +> **Note:** If you are upgrading from version 3.5.0 or below. you need to follow below steps +> 1. Update runbook files with latest compatible version +*"Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -OverrideBaseConfig CARunbooks"* If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. +> 2. If Org policy is customized with SecurityCenter configurations. You have to update policy with latest (SecurityCenter.json) schema from 3.6.1. + + +* Fixed issue related to ASC API in GSS command. Any subscription not having security contacts details setup, ASC API was throwing exception and causing issue (InvalidOperation: The remote server returned an error: (404) Not Found.) + +* Fixed issue for express route connected VM. (The property 'Tags' cannot be found on this object. Verify that the property exists.) + + +# AzSK v.3.6.0 +>**Note:** AzSK 3.6.0 has upgraded with breaking changes for RunbookCoreSetup present on Custom Org Policy. You will need to take latest runbook files with update Org policy command (*Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -OverrideBaseConfig CARunbooks*). If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. + +* Ability to let customers control the default location where AzSK root resources will get created for subscriptions that are onboarded (for manual, CA or CICD scanning). +* Fixed bug for Manual control where its settings not getting respected with Org policy setup. + + +# AzSK v.3.5.0 + +>**Note:** AzSK 3.5.0 has upgraded its dependancy on AzureRM and now requires AzureRM version 6.x. It has breaking changes for RunbookCoreSetup and RunbookScanAgent present on Custom Org Policy. If you are upgrading Org Policy with AzSK version 3.5.0 using configurations(AzSK.Pre.Json), you will need to take latest runbook files with update Org policy command (*Update-AzSKOrganizationPolicy -SubscriptionId `` -OrgName `` -DepartmentName `` -OverrideBaseConfig CARunbooks*). If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. + +* Policy owner can now use a local folder to ‘deploy’ policy to significantly improve debugging/troubleshooting experience. (Policy changes can be pre-tested locally and there’s no need to maintain a separate dev-test policy server endpoint.) +* Support for handling expiry of SAS token in the policy URL in an automated manner in local setup and CA. (Only CICD extension scenarios will need explicit updates. We will display warnings when expiry is coming up in the next 30 days.) +* Support for schema validation of org policy config JSON via the Get-AzSKOrganizationPolicyStatus command. This will reduce chances of errors due to oversight/copy-paste errors, etc. +* Teams that extend the AzSK module can now also add custom listeners to receive scan events. + +# AzSK v.3.4.x + +* A new cmdlet (Get-AzSKOrganizationPolicyStatus) to check health/correctness of org policy configuration for a given setup and to also help remediate issues that were found. +* Provided option to download existing policies from the policy server. +* If an org is using a version of AzSK that is more than 2 releases old (current-2), then we will show a ‘deprecated’ warning to ensure that customers using org policy are staying up to date with the latest security controls. +* If a subscription is configured with a specific org policy then the scan commands run using some other (or OSS) policy will be disallowed with appropriate warnings. +* Org policy customers can now generate compliance dashboard based on a Power BI content pack and a CSV mapping subscription to org details. + diff --git a/07-Customizing-AzSK-for-your-Org/Readme.md b/07-Customizing-AzSK-for-your-Org/Readme.md index 5b65aa9f..3f928329 100644 --- a/07-Customizing-AzSK-for-your-Org/Readme.md +++ b/07-Customizing-AzSK-for-your-Org/Readme.md @@ -1,6 +1,11 @@ -# Customizing AzSK for your organization +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- -### [Overview](Readme.md#overview-1) +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# Customizing AzSK for your organization + +### [Overview](Readme.md#Overview-1) - [When and why should I set up org policy?](Readme.md#when-and-why-should-i-setup-org-policy) - [How does AzSK use online policy?](Readme.md#how-does-azsk-use-online-policy) @@ -9,17 +14,85 @@ - [The org policy setup command: Install-AzSKOrganizationPolicy](Readme.md#the-org-policy-setup-command-install-azskorganizationpolicy) - [First-time policy setup - an example](Readme.md#first-time-policy-setup---an-example) +### [Consuming custom org policy](Readme.md#consuming-custom-org-policy-1) + + - [Running scan in local machine with org policy](Readme.md#1-running-scan-in-local-machine-with-custom-org-policy) + - [Setup Continuous Assurance](Readme.md#2-setup-continuous-assurance) + - [Using CICD Extension with org-policy](Readme.md#3-using-cicd-extension-with-custom-org-policy) + ### [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy-1) - - [Common scenarios for org policy customization](Readme.md#common-scenarios-for-org-policy-customization) - - [Using CICD Extension with custom org-policy](Readme.md#using-cicd-extension-with-custom-org-policy) - - [Next Steps](Readme.md#next-steps) + - [Getting Started](Readme.md#getting-started) -### [Testing and troubleshooting org Policy](Readme.md#testing-and-troubleshooting-org-policy-1) - - [Testing the overall policy setup](Readme.md#testing-the-overall-policy-setup) - - [Troubleshooting common issues](Readme.md#troubleshooting-common-issues) - + - [Basic scenarios for org policy customization](Readme.md#basic-scenarios-for-org-policy-customization) + + - [Changing the default 'Running AzSK using…' message](Readme.md#a-changing-the-default-running-azsk-using-message) + - [Changing control setting](Readme.md#b-changing-a-control-setting-for-specific-controls) + - [Customizing specific controls for a service SVT](Readme.md#c-customizing-specific-controls-for-a-service) + - [Setting up and updating baselines for your org](Readme.md#d-creating-a-custom-control-baseline-for-your-org) + - [Customizing severity labels](Readme.md#e-customizing-severity-labels) + +### [Managing policy/advanced policy usage ](Readme.md#managing-policyadvanced-policy-usage) + +- [Downloading and examining policy folder](Readme.md#downloading-and-examining-policy-folder) + +- [Working with ‘local’ mode (policy dev-test-debug)](Readme.md#working-with-local-mode-policy-dev-test-debug) + +- [How to upgrade org version to latest AzSK version](Readme.md#how-to-upgrade-org-azsk-version-to-the-latest-azsk-version) + + + - [Upgrade scenarios in different scan sources(SDL/CA/CICD)](Readme.md#upgrade-scenarios-in-different-scan-sources) + +- [Maintaining policy in source-control](Readme.md#maintaining-policy-in-source-control) + +- [Policy deployment using CICD pipeline](Readme.md#policy-deployment-using-cicd-pipeline) + + +### [Create compliance and monitoring solutions](Readme.md#create-security-compliance-monitoring-solutions) + +- [Create cloud security compliance report for your org in PowerBI](Readme.md#create-cloud-security-compliance-report-for-your-org-using-powerbi) + +- [AzSK org health monitoring dashboard](Readme.md#azsk-org-health-monitoring-dashboard) + +- [Detail resource inventory dashboard](Readme.md#detail-resource-inventory-dashboard) + + +### [Compliance notifications](Readme.md#compliance-notifications-1) + +- [Create compliance notification to subscription owners](Readme.md#compliance-notification-to-subscription-owners) + + +### [Advanced scenarios for org policy customization/extending AzSK](Readme.md#advanced-usage-of-org-policy-extending-azsk) + +- [SVT customization](Readme.md#customizing-the-svts) + - [Update/extend existing control by augmenting logic](./Extending%20AzSK%20Module/Readme.md#steps-to-override-the-logic-of-existing-svt) + - [Add new control for existing GSS/GRS SVT](./Extending%20AzSK%20Module/Readme.md#steps-to-extend-the-control-svt) + - [Add new SVT altogether (non-existing SVT)](./Extending%20AzSK%20Module/Readme.md#steps-to-add-a-new-svt-to-the-azsk-module) + +- [Subscription security provisioning](Readme.md#customizing-subscription-security) + - [ARM policy](Readme.md#arm-policy) + - [Alert set](Readme.md#alert-set) + - [Security center configurations](Readme.md#security-center-configurations) + - [Mandatory/deprecated RBAC list](Readme.md#rbac-mandatorydeprecated-lists) + +- [ARM checker policy customization](Readme.md#arm-checker-policy-customization) + +- [Scenarios for modifying scanagent](Readme.md#scenarios-for-modifying-scanagent) + - [Scanning only baseline controls using continuous assurance setup](Readme.md#scanning-only-baseline-controls-using-continuous-assurance-setup) + - [Scanning admin and graph access controls using CA](Readme.md#scanning-owner-and-graph-access-controls-using-ca) + - [Reporting critical alerts](#reporting-critical-alerts) + + +- [Change default resource group name (AzSKRG) and location (EastUS2) created for AzSK components](Readme.md#change-default-resource-group-name-(AzSKRG)-and-location-(EastUS2)-created-for-AzSK-components) + +### [Org policy usage statistics and monitoring using telemetry](Readme.md#org-policy-usage-statistics-and-monitoring-using-telemetry-1) + + +### [Troubleshooting common issues](Readme.md#testing-and-troubleshooting-org-policy-1) +### [Frequently Asked Questions](Readme.md#frequently-asked-questions) + ---------------------------------------------------------------- ## Overview @@ -44,10 +117,10 @@ This includes things such as: Note that the policy files needed for security scans are downloaded into each PS session for **all** AzSK scenarios. That is, apart from manually-run scans from your desktop, this same behavior happens if you include the AzSK SVTs Release Task in your CICD pipeline or if you setup Continuous Assurance. -Also, the AzSK policy files on the CDN are based on what we use internally in Core Services Engineering -(CSE) at Microsoft. We also keep them up to date from one release to next . +Also, the AzSK policy files on the CDN are based on what we use internally in Core Services Engineering and Operations +(CSEO) at Microsoft. We also keep them up to date from one release to next. - + @@ -71,8 +144,7 @@ Let us look at how policy files are leveraged in a little more detail. When you install AzSK, it downloads the latest AzSK module from the PS Gallery. Along with this module there is an *offline* set of policy files that go in a sub-folder under the %userprofile%\documents\WindowsPowerShell\Modules\AzSK\ folder. -It also places (or updates) an AzSKSettings.JSON file in your %LocalAppData%\AzSK folder. It is this latter -file that contains the policy endpoint (or policy server) URL that is used by all local commands. +It also places (or updates) an AzSKSettings.JSON file in your %LocalAppData%\Microsoft\AzSK folder that contains the policy endpoint (or policy server) URL that is used by all local commands. Whenever any command is run, AzSK uses the policy server URL to access the policy endpoint. It first downloads a 'metadata' file that contains information about what other files are available on the policy server. After @@ -89,7 +161,7 @@ overridden for a specific feature (e.g., Storage), then it won't find a policy f The image below shows this flow with inline explanations: -Effective Org Policy Evaluation +Effective org Policy Evaluation ## Setting up org policy @@ -113,108 +185,230 @@ Let us now look at the command that will help with the above and a few examples #### The org policy setup command (`Install-AzSKOrganizationPolicy`) This command helps the central security team of an organization to customize the behavior of various functions -and security controls checked by AzSK.  +and security controls checked by AzSK. As discussed in previous sections, AzSK runtime behavior is mainly controlled through JSON-based policy files which have a predefined schema. The command helps in creating a policy store and other required components to -host and maintain a custom set of policy files that override the default AzSK behavior.  +host and maintain a custom set of policy files that override the default AzSK behavior. -| Parameter| Description | Required? | Default Value | Comments | +| Parameter| Description | Required? | Default Value | Comments | | ---- | ---- | ---- |----|---- | -| SubscriptionId | Subscription ID of the Azure subscription in which organization policy store will be created. | Yes | None | -|OrgName | The name of your organization. The value will be used to generate names of Azure resources being created as part of policy setup. This should be alphanumeric. | Yes | None | -| DepartmentName | The name of a department in your organization. If provided, this value is concatenated to the org name parameter. This should be alphanumeric. | No | None | -| PolicyFolderPath | The local folder in which the policy files capturing org-specific changes will be stored for reference. This location can be used to manage policy files. | No | User Desktop | -| ResourceGroupLocation | The location in which the Azure resources for hosting the policy will be created. | No | EastUS2 | To obtain valid locations, use Get-AzureRMLocation cmdlet | - +| SubscriptionId | Subscription ID of the Azure subscription in which organization policy store will be created. | Yes | None | +|OrgName | The name of your organization. The value will be used to generate names of Azure resources being created as part of policy setup. This should be alphanumeric. | Yes | None | +| DepartmentName | The name of a department in your organization. If provided, this value is concatenated to the org name parameter. This should be alphanumeric. | No | None | +| PolicyFolderPath | The local folder in which the policy files capturing org-specific changes will be stored for reference. This location can be used to manage policy files. | No | User Desktop | +| ResourceGroupLocation | The location in which the Azure resources for hosting the policy will be created. | No | EastUS2 | To obtain valid locations, use Get-AzLocation cmdlet | +| ResourceGroupName | Resource Group name where policy resources will be created. | No | AzSK-\-\-RG | Custom resource group name for storing policy resources. **Note:** ResourceGroupName, StorageAccountName and AppInsightName must be passed together to create custom resources. The same parameters must be used to update org policy. | +| StorageAccountName | Name for policy storage account | No | azsk-\-\-sa | | +| AppInsightName | Name for application insight resource where telemetry data will be pushed | No | AzSK-\--AppInsight | | +| AppInsightLocation | The location in which the AppInsightLocation resource will be created. | No | EastUS | | #### First-time policy setup - an example -The following example will set up policies for IT department of Contoso organization. +The following example will set up policies for IT department of Contoso organization. -You must be an 'Owner' or 'Contributor' for the subscription in which you want to host your org's policy artefacts. -Also, make sure that that the org name and dept name are purely alphanumeric and their combined length is less that 19 characters. +You must be an 'Owner' or 'Contributor' for the subscription in which you want to host your org's policy artifacts. +Also, make sure that that the org name and dept name are purely alphanumeric and their combined length is less than 19 characters. The policy setup command is fairly lightweight - both in terms of effort/time and in terms of costs incurred. ```PowerShell -Install-AzSKOrganizationPolicy -SubscriptionId `  -           -OrgName "Contoso" `  -           -DepartmentName "IT" `  -           -PolicyFolderPath "D:\ContosoPolicies" +Install-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" ``` -The execution of command will create following resources in the subscription (if they don't already exist):  + +> **Note:** For Azure environments other than Azure Cloud (like Azure Gov, China etc.), don't forget to provide ResourceGroupLocation as the default value won't work in those environments. + +The execution of command will create following resources in the subscription (if they don't already exist): 1. Resource Group (AzSK-Contoso-IT-RG) - AzSK-\-\-RG. 2. Storage Account (azskcontosoitsa) - azsk\\sa. -3. Application Insight (AzSK-Contoso-IT-AppInsight) - AzSK-\-\-AppInsight.  +3. Application Insight (AzSK-Contoso-IT-AppInsight) - AzSK-\-\-AppInsight. +4. Monitoring dashboard (DevOpsKitMonitoring (DevOps Kit Monitoring Dashboard [Contoso-IT])) + +> **Note:** You must not have any other resources than created by setup command in org policy resource group. + +It will also create a very basic 'customized' policy involving below files uploaded to the policy storage account. + +##### Basic files setup during Policy Setup + +| File | Container | Description +| ---- | ---- | ---- | +| AzSK-EasyInstaller.ps1 | installer | Org-specific installation script. This installer will ensure that anyone who installs AzSK using your 'iwr' command not only gets the core AzSK module but their local installation of AzSK is also configured to use org-specific policy settings (e.g., policy server URL, telemetry key, etc.) **IMPORTANT:** Make sure anyone in your org who needs to scan according to your policies uses the above 'iwr' command to install AzSK. (They should not use 'install-module AzSK' directly. Anyone using an incorrect setup will not get your custom policy when they run any AzSK cmdlet. | +| AzSK.Pre.json | policies | This file contains a setting that controls/defines the AzSK version that is 'in effect' at an organization. An org can use this file to specify the specific version of AzSK that will get used in SDL/CICD/CA scenarios at the org for people who have used the org-specific 'iwr' to install and configure AzSK.

    **Note:** During first time policy setup, this value is set with AzSK version available on the client machine that was used for policy creation. Whenever a new AzSK version is released, the org policy owner should update the AzSK version in this file with the latest released version after performing any compatibility tests in a test setup.
    You can get notified of new releases by following the AzSK module in PowerShell Gallery or release notes section [here](https://azsk.azurewebsites.net/ReleaseNotes/LatestReleaseNotes.html). +| RunbookCoreSetup.ps1 | policies | Used in Continuous Assurance to setup AzSK module +| RunbookScanAgent.ps1 | policies | Used in Continuous Assurance to run daily scan +| AzSk.json | policies | Includes org-specific message, telemetry key, InstallationCommand, CASetupRunbookURL etc. +| ServerConfigMetadata.json | policies | Index file with list of policy files. + + +Output of command looks like below + +Effective org Policy Evaluation + + +If you note section 3 of the command output , an 'iwr' command line is printed to the console. This command leverages the org-specific + installation script from the storage account for installing AzSK. You can run this IWR followed by some scan commands (GSS/GRS) to see org policy in effect in your dev box. -It will also create a very basic 'customized' policy involving just a single change (an org-specific message -in AzSk.json) and upload AzSk.json, ServerConfigMetadata.json files to the storage account. It will also -upload an org-specific installation script called AzSK-EasyInstaller.ps1 to another container within the same -storage account and another file called ScanAgent.ps1 which is used to support the Continuous Assurance feature. -At the end of execution, an 'iwr' command line will be printed to the console. This command leverages the org-specific - installation script from the storage account for installing AzSK. The org-specific installer will ensure that -anyone who installs AzSK using your 'iwr' command not only gets the core AzSK module but their local installation -of AzSK is also configured to use org-specific policy settings (e.g., policy server URL, telemetry key, etc.) ```PowerShell -iwr 'https://azskcontosoitsa.blob.core.windows.net/installer/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex  +#IWR to install org specific configurations +iwr 'https://azskcontosoitsa.blob.core.windows.net/installer/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex + +#Subscription Scan with org policy +Get-AzSKSubscriptionSecurityStatus -SubscriptionId ``` + Output: -## Modifying and customizing org policy  +Effective org Policy Evaluation -All subsequent runs of the (same) command above will pick up the JSON files from local PolicyFolderPath and upload -to policy store, provided the values for OrgName and DepartmentName remain unchanged. (This is required -because the command internally evaluates the locations of various artifacts based on these values.) To modify policy -or add more policy customizations, we shall be reusing the same command as used for first-time setup. -> **Note**: ServerConfigMetadata.json and AzSK-EasyInstaller.ps1 will always get overwritten on the subsequent run of the command.  +## Next Steps: - -#### Common scenarios for org policy customization +Once your org policy is setup, all scenarios/use cases of AzSK should work seamlessly with your org policy server +as the policy endpoint for your org (instead of the default CDN endpoint). Basically, you should be able to do one +or more of the following using AzSK: + + - People will be able to install AzSK using your special org-specific installer (the 'iwr' install command) + - Developers will be able to run manual scans for security of their subscriptions and resources (GRS, GSS commands) + - Teams will be able to configure the AzSK SVT release task in their CICD pipelines + - Subscription owners will be able to setup Continuous Assurance (CA) from their local machines (**after** they've installed + AzSK using your org-specific 'iwr' installer locally) + - Monitoring teams will be able to setup AzSK Log Analytics view and see scan results from CA (and also manual scans and CICD if configured) + - You will be able to do central governance for your org by leveraging telemetry events that will collect in the master subscription + from all the AzSK activity across your org. -In this section let us look at typical use cases for org policy customization and how to accomplish them. -We will cover the following: +## Consuming custom org policy -1. Changing the default 'Running AzSK using…' message -2. Changing a global setting for some control -3. Changing/customizing a server baseline policy set -4. Customizing specific controls for a service SVT (e.g., Storage.json) - 1. Turning controls On/Off - 2. Changing Recommendation Text - 3. Changing Severity, etc. -5. Changing ARM policy/Alerts set (coming soon…) -6. Changing RBAC mandatory/deprecated lists (coming soon…) +Running scan with custom org policy is supported from all three avenues of AzSK viz. local scan (SDL), continuous assurance setup and CICD SVT task. Follow the steps below for the same: +### 1. Running scan in local machine with custom org policy -> Note: To edit policy JSON files, use a friendly JSON editor such as Visual Studio Code. It will save you lot of -> debugging time by telling you when objects are not well-formed (extra commas, missing curly-braces, etc.)! This -> is key because in a lot of policy customization tasks, you will be taking existing JSON objects and removing -> large parts of them (to only keep the things you want to modify). + To run scan with custom org policy from any machine, get IWR cmdlet from org policy owner. This IWR is generated at the time of policy setup (IOP) or policy update (UOP) in the following format + +```PowerShell +#Sample IWR to install org specific configurations +iwr 'https://azskcontosoitsa.blob.core.windows.net/installer/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex + +#Run subscription scan cmdlet and validate if it is running with org policy +Get-AzSKSubscriptionSecurityStatus -SubscriptionId +``` + +This step is pre-requisite for the other two scan methods. + +### 2. Setup Continuous Assurance + +Setting up CA with org policy is pretty simple. Once you have followed the first step i.e. running iwr in local machine, you can run CA setup with the help of doc [here](https://github.com/azsk/DevOpsKit-docs/blob/master/04-Continous-Assurance/Readme.md#setting-up-continuous-assurance---step-by-step). +CA setup command will refer policy setting from your local machine and configure it in automation runbook. +For existing CA, you just need to run *Update-AzSKContinuousAssurance* in your local. + + +You can validate if CA is running with custom org policy, via the options below: + + Option 1: + + Go to central CA resource group --> automation account --> Jobs --> Open one of the completed jobs --> It prints initials of PolicyStoreURL (Policy Store URL is nothing but org policy storage account blob url) + + ![AzSK org policy check using runbook ](../Images/07_OrgPolicy_CA_PolicyCheck-0.PNG) + + Option 2: + + i) Download latest AzSK Scan logs stored in storage account (inside AzSKRG) + + ![AzSK Scan Logs](../Images/07_OrgPolicy_CA_PolicyCheck-1.PNG) + + ii) Open PowerShellOutput.log file under etc folder and validate policy name + + ![AzSK Scan Logs](../Images/07_OrgPolicy_CA_PolicyCheck-2.PNG) + + Option 3: + + Go to Log Analytics workspace which was configured during CA setup and execute below query + + ```AI Query + AzSK_CL | where Source_s == "CA" | summarize arg_max(TimeGenerated,*) by SubscriptionId | project SubscriptionId,PolicyOrgName_s | render table + ``` + It will show the subscriptions running with org policy in a table as depicted below: + + ![AzSK Scan Logs](../Images/07_OrgPolicy_CA_PolicyCheck-3.PNG) + + +### 3. Using CICD Extension with custom org policy + +To set up CICD when using custom org policy, please follow below steps: +1. Add Security Verification Tests (SVTs) in VSTS pipeline by following the steps [here](../03-Security-In-CICD#adding-svts-in-the-release-pipeline). +2. Make sure AzSKServerURL and EnableServerAuth settings in the AzSK_SVTs task are setup correctly (Refer step 5 in the document referred above) + +Having set the policy URL along with AzSK_SVTs Task, you can verify if your CICD task has been properly setup by following steps [here](../03-Security-In-CICD#verifying-that-the-svts-have-been-added-and-configured-correctly). + + + +Policy owner can monitor the subscriptions being scanned from different environments with the help of application insight telemetry. + +```AI Query +customEvents +| where timestamp >= ago(7d) +| where name == "Control Scanned" +| summarize arg_max(timestamp, *) by Day = bin(timestamp,1d), ScanSource = tostring(customDimensions.ScanSource),tostring(customDimensions.SubscriptionId) +| summarize SubscriptionCount = count() by Day, ScanSource +| render barchart +``` +Output: + +![AzSK Scan Logs](../Images/06_AIGraph_Usage.PNG) + + +## Modifying and customizing org policy -The general workflow for all policy changes will be similar and involve the following steps: +#### Getting Started + +The typical workflow for all policy changes will remain same and will involve the following basic steps: + + 1) Go to the folder on your dev box which has your org-customized policies. This could either be the folder you specified while running org policy setup command or the default one used by it. If you don't have policies on your dev box, you can download those using the following cmdlet. (Please note that the OrgName, DepartmentName and PolicyFolderPath values are for illustration only. You may need to replace them with the ones used during your org policy setup.) + + ```PowerShell + Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -DownloadPolicy ` + -PolicyFolderPath "D:\ContosoPolicies" + ``` + + + 2) Make modifications to the existing files (or add additional policy files as required) + 3) Run the policy update command to upload all artifacts to the policy server (*Update-AzSKOrganizationPolicy*). It is possible to test policies in local before uploading to server. We will cover this scenario in detail further in this document. + 4) Test in a fresh PS console that the policy change is in effect. (Policy changes do not require re-installation of AzSK.) - 1) Go to the folder you have used (or the org-setup command auto-generated) for your org-customized policies - 2) Make any modifications to existing files (or add additional policy files as required) - 3) Make sure that there's an entry in the ServerConfigMetadata.json file for all the files you have modified - (Make sure that this entry matches the file names with correct case!) - 4) Run the policy update command to upload all artifacts to the policy server - 5) Test in a fresh PS console that the policy change is in effect. (Policy changes do not require re-installation of AzSK.) Note that you can upload policy files from any folder (e.g., a clone of the originally used/created one). It just needs to have the same folder structure as the default one generated by the first-time policy setup and you must specify the folder path using the '-PolicyFolderPath' parameter. -Because policy on the server works using the 'overlay' approach, the corresponding file on the server -only needs to have the specific changes that are required (plus some identifying elements in some cases). +Because policy on the server works using the 'overlay' approach, **the corresponding file on the server +needs to have only those specific changes that are required (plus some identifying elements in some cases).** -Lastly, note that when making modifications we will **never** edit the files that came with the AzSK installation. -We will create copies of the files we wish to edit, place them in our org-policy folder and make requisite +Lastly, note that while making modifications, you should **never** edit the files that came with the AzSK installation folder(%userprofile%\documents\WindowsPowerShell\Modules\AzSK). +You should create copies of the files you wish to edit, place them in our org-policy folder and make requisite modifications there. +> **Note**: ServerConfigMetadata.json and AzSK-EasyInstaller.ps1 will always get overwritten on the subsequent run of the command. + + +### Basic scenarios for org policy customization + + +In this section let us look at typical scenarios in which you would want to customize the org policy and ways to accomplish them. + +> Note: To edit policy JSON files, use a friendly JSON editor such as Visual Studio Code. It will save you lot of +> debugging time by telling you when objects are not well-formed (extra commas, missing curly-braces, etc.)! This +> is key because in a lot of policy customization tasks, you will be taking existing JSON objects and removing +> large parts of them (to only keep the things you want to modify). + + ##### a) Changing the default `'Running AzSK using...'` message -Whenever any user in your org runs an AzSK command after having installed AzSK using your org-specific installer, +Whenever any user in your org runs an AzSK command after having installed AzSK using your org-specific installer (IWR), they should see a message such as the following (note the 'Contoso-IT') indicating that AzSK is running using an org-specific policy: - Running AzSK cmdlet using Contoso-IT policy + Running AzSK cmdlet using ***Contoso-IT*** policy -Notice that here, the default (first time) org policy setup injects the 'Contoso-IT' based on the OrgName and +Notice that here, the default (first-time) org policy setup injects the 'Contoso-IT' based on the OrgName and the DeptName that you provided when you setup your org policy server. (When users are running without your org policy correctly setup, they will see the 'Running AzSK cmdlet using generic (org-neutral) policy' message which comes from the AzSK public CDN endpoint.) @@ -224,20 +418,38 @@ from the server version of this file. You may want to change this message to something more detailed. (Or even use this as a mechanism to notify all users within the org about something related to AzSK that they need to attend to immediately.) -In this example let us just make a simple change to this message. We will just add '*' characters on either side +In this example let us just make a simple change to this message. We will just more '*' characters on either side of the 'Contoso-IT' so it stands out a bit. ###### Steps: - i) Open the AzSk.json from your local org-policy folder + i) Open the AzSk.json from your local org-policy folder. + Path from example: D:\ContosoPolicies\Config\AzSK.json - ii) Edit the value for "Policy Message" field by adding 3 '*' characters on each side of 'Contoso-IT' as under: -``` - "PolicyMessage" : "Running AzSK cmdlet using *** Contoso-IT *** policy" -``` + ii) Edit the value for "Policy Message" field by adding 5 '*' characters on each side of 'Contoso-IT' as under: + ``` + "PolicyMessage" : "Running AzSK cmdlet using ***** Contoso-IT ***** policy" + ``` iii) Save the file - iv) Run the policy setup command (the same command you ran for the first time setup) + iv) Run the policy update command + +```PowerShell +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" + + #If custom resource names are used during setup, you can use below parameters to download policy + +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "Contoso-IT-RG" ` + -StorageAccountName "contosoitsa" ` + -AppInsightName "ContosoITAppInsight" ` + -PolicyFolderPath "D:\ContosoPolicies" +``` + ###### Testing: @@ -245,14 +457,46 @@ The updated policy is now on the policy server. You can ask another person to te (e.g., Get-AzSKInfo) in a **fresh** PS console. When the command starts, it will show an updated message as in the image below: -![Org Policy - Changed Message](../Images/07_OrgPolicy_Chg_Org_Policy_Msg_PS.PNG) +![org Policy - Changed Message](../Images/07_OrgPolicy_Chg_Org_Policy_Msg_PS.PNG) -This change will be immediately in effect across your organization. Anyone running AzSK commands (in fresh PS sessions) +This change will be effective across your organization immediately. Anyone running AzSK commands (in fresh PS sessions) should see the new message. -##### b) Changing a control setting for specific controls -Let us now change some numeric setting for a control. A typical setting you may want to tweak is the count of -maximum owners/admins for your org's subscriptions that is checked in one of the subscription security controls. (The out-of-box default is 5.) +##### b) Customize output folder for my org +Usually, when we run AzSK command the results go to the default folder i.e. +C:\Users\\AppData\Local\Microsoft\AzSKLogs\Sub_[yourSubscriptionName]\20170331_142819. +The default location for log storage can be customized in a custom org policy setup. Post customization the scan results will be stored in that particular location. + +###### Steps: + +i) Open the AzSk.json from your local org-policy folder that you have downloaded using. + +```PowerShell +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -DownloadPolicy ` + -PolicyFolderPath "D:\ContosoPolicies" +``` + +ii) Add a new property 'OutputFolderPath' and provide the required destination path where you want to store the scan results. +E.g. +```PowerShell + "OutputFolderPath": "" # D:\AzSKLogs +``` +iii) Save the AzSK.json file and rerun the policy update or setup command (the same command you ran for the first-time setup) + +###### Testing: + +You can validate the changes by running ‘gai -infotype hostinfo’. +![Validate-OutputFolderPath](../Images/07_Custom_Policy_Output_Folder_path.PNG) + +Now if anyone in your org starts a fresh PS session and runs AzSK scan, the results will be stored in the location defined in the OutputFolderPath property added in step ii. +![Store Log-Given path](../Images/07_Custom_Policy_Scan_Result.PNG) + +##### c) Changing a control setting for specific controls +Let us now change some numeric setting for a control. A typical setting you may want to tweak is the maximum number of +owners/admins allowed for your org's subscriptions. It is verified in one of the subscription security controls. (The default value is 5.) This setting resides in a file called ControlSettings.json. Because the first-time org policy setup does not customize anything from this, we will first need to copy this file from the local AzSK installation. @@ -278,55 +522,95 @@ Rather, **always** copy the file to your own org-policy folder and edit it there iii) Save the file - iv) Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) + iv) Rerun the policy update or setup command (the same command you ran for the first-time setup) + +###### Testing: + +Anyone in your org can now start a fresh PS console and the result of the evaluation of the number of owners/admins control in +the subscription security scan (Get-AzSKSubscriptionSecurityStatus) should reflect that the new setting is in +effect. (E.g., if you change the max count to 3 and they had 4 owners/admins in their subscription, then the result for control (Azure_Subscription_AuthZ_Limit_Admin_Owner_Count) will change from 'Passed' to 'Failed'.) + +##### d) Customizing specific controls for a service + +In this example, we will make a slightly more involved change in the context of a specific SVT (Storage). + +Imagine that you want to turn off the evaluation of some control altogether (regardless of whether people use the `-UseBaselineControls` parameter or not). +Also, for another control, you want people to use a recommendation which leverages an internal tool the security team +in your org has developed. Let us do this for the Storage.json file. Specifically, we will: +1. Turn off the evaluation of `Azure_Storage_Audit_Issue_Alert_AuthN_Req` altogether. +2. Modify severity of `Azure_Storage_AuthN_Dont_Allow_Anonymous` to `Critical` for our org (it is `High` by default). +3. Change the recommendation for people in our org to follow if they need to address an issue with the `Azure_Storage_DP_Encrypt_In_Transit` control. +4. Disable capability to attest the control `Azure_Storage_DP_Restrict_CORS_Access` by adding 'ValidAttestationStates' object. + +###### Steps: + + i) Copy the Storage.json from the AzSK installation to your org-policy folder -![Entry in ServerConfigMetadata.json](../Images/07_OrgPolicy_Chg_SCMD_Entry.PNG) + ii) Remove everything except the ControlID, the Id and specific property we want to modify as mentioned above. + + iii) Make changes to the properties of the respective controls so that the final JSON looks like the below. ```JSON { - "OnlinePolicyList" : [ - { - "Name" : "AzSk.json" - }, - { - "Name" : "ControlSettings.json" - } - ] + "Controls": [ + { + "ControlID": "Azure_Storage_AuthN_Dont_Allow_Anonymous", + "Id": "AzureStorage110", + "ControlSeverity": "Critical" + }, + { + "ControlID": "Azure_Storage_Audit_Issue_Alert_AuthN_Req", + "Id": "AzureStorage120", + "Enabled": false + }, + { + "ControlID": "Azure_Storage_DP_Encrypt_In_Transit", + "Id": "AzureStorage160", + "Recommendation": "**Note**: Use our Contoso-IT-EncryptInTransit.ps1 tool for this!" + }, + { + "ControlID": "Azure_Storage_DP_Restrict_CORS_Access", + "ValidAttestationStates" : ["None"] + } + ] } ``` +> **Note:** The 'Id' field is used for identifying the control for policy merging. We are keeping the 'ControlID' +> field only because of the readability. + + iii) Save the file - v) Rerun the policy setup command (the same command you ran for the first time setup) + iv) Rerun the org policy update or setup command (the same command you ran for the first-time setup) ###### Testing: +Someone in your org can test this change using the `Get-AzSKAzureServicesSecurityStatus` command on a target +resource group which contains a storage account. If run with the `-UseBaselineControls` switch, you will see that +the control Azure_Storage_AuthN_Dont_Allow_Anonymous shows as `Critical` in the output CSV and the recommendation for control Azure_Storage_DP_Encrypt_In_Transit has changed to +the custom (internal tool) recommendation you wanted people in your org to follow. -Anyone in your org can now start a fresh PS console and the result of the evaluation of the number of owners/admins control in -the subscription security scan (Get-AzSKSubscriptionSecurityStatus) should reflect that the new setting is in -effect. (E.g., if you changes the max count to 3 and they had 4 owners/admins in their subscription, then the control -result will change from 'Passed' to 'Failed'.) +Likewise, even after you run the scan without the `-UseBaselineControls` parameter, you will see that the control Azure_Storage_Audit_Issue_Alert_AuthN_Req is not evaluated and does not +appear in the resulting CSV file. -##### c) Creating a custom control 'baseline' for your org -Note that a powerful capability of AzSK is the ability for an org to define a baseline control set on the policy server +##### e) Creating a custom control 'baseline' for your org +A powerful capability of AzSK is the ability for an org to define a baseline control set on the policy server that can be leveraged by all individuals in the org (and in other AzSK scenarios like CICD, CA, etc.) via the "-UseBaselineControls" parameter during scan commands. -By default, when someone runs against the CDN endpoint, the "-UseBaselineControls" parameter leverages the set of -controls listed as baseline in the ControlSettings.json file present on CDN. +By default, when someone runs the scan with "-UseBaselineControls" parameter, it leverages the set of +controls listed as baseline in the ControlSettings.json file present on default AzSK CDN endpoint. -However, once you have set up an org policy server for your organization, the CDN endpoint is no more in use. (As a +However, once you have set up an org policy server for your organization, this CDN endpoint is no more in use. (As a side note, you can always 'simulate' CDN-based/org-neutral execution by removing or renaming your `%localappdata%\Microsoft\AzSK\AzSKSettings.json` file.) Thus, after org policy is setup, there will not be a 'baseline' control set defined for your organization. Indeed, if you run any of the scan commands using the -"-UseBaselineControls" switch, you will see that the switch gets ignored and **all** controls for respective -resources are evaluated. +"-UseBaselineControls" switch, you will see exception "There are no baseline controls defined for your org. No controls will be scanned." -To support the baseline controls behavior for your org, you will need to define your baseline in the ControlSettings.json -file. Here are the steps... - -###### Steps: - -(We will assume you have tried the max owner/admin count steps in (b) above and edit the ControlSettings.json -file already present in your org policy folder.) +To define baseline controls for your org, you will need to define update the ControlSettings.json +file as per the steps below- + +(We assume that you have tried the max owner/admin count steps in (b) above and edited the ControlSettings.json +file is already present in your org policy folder.) i) Edit the ControlSettings.json file to add a 'BaselineControls' object as per below: @@ -346,7 +630,7 @@ file already present in your org policy folder.) "ResourceType": "Storage", "ControlIds": [ "Azure_Storage_AuthN_Dont_Allow_Anonymous", - "Azure_Storage_Deploy_Use_Geo_Redundant" + "Azure_Storage_DP_Encrypt_In_Transit" ] } ], @@ -354,27 +638,23 @@ file already present in your org policy folder.) "Azure_Subscription_AuthZ_Limit_Admin_Owner_Count", "Azure_Subscription_AuthZ_Dont_Use_NonAD_Identities", "Azure_Subscription_Config_Azure_Security_Center" - ], - "ExpiryInDays": 6, - "SupportedSources": [ "CC" ] + ] } } ``` > Notice how, apart from the couple of extra elements at the end, the baseline set is pretty much a list of 'ResourceType' -and 'ControlIds' for that resource...making it fairly easy to customize/tweak your own org baseline. -> Here the name and casing of the resource type name must match that of the policy JSON file for the corresponding -> resource's JSON file in the SVT folder and the control ids must match those included in the JSON file. +and 'ControlIDs' for that resource...making it fairly easy to customize/tweak your own org baseline. +> Here the name and casing of the resource type name must match that of the policy JSON file for the corresponding resource's JSON file > in the SVT folder and the control ids must match those included in the JSON file. > Note: Here we have used a very simple baseline with just a couple of resource types and a very small control set. -> A more realitic baseline control set will be more expansive. -> +> A more realistic baseline control set will be more expansive. You can refer CSEO defined baseline using ControlSettings file [here](https://github.com/azsk/DevOpsKit/blob/master/src/OSSConfiguration/ControlSettings.json). ii) Save the ControlSettings.json file iii) Confirm that an entry for ControlSettings.json is already there in the ServerConfigMetadata.json file. (Else see step-iii in (c) above.) - iv) Run the policy setup command (the same command you ran for the first time setup) + iv) Run the policy setup command (the same command you ran for the first-time setup) ###### Testing: @@ -384,145 +664,1013 @@ types of Azure resources present in their subscriptions, only the ones mentioned and, even for those, only the baseline controls get evaluated. -##### d) Customizing specific controls for a service +> **Note:** Similar to baseline control, you can also define preview baseline set with the help of similar property "PreviewBaselineControls" in ControlSettings.json. This preview set gets scanned using parameter `-UsePreviewBaselineControls` with scan commands. -In this example, we will make a slightly more involved change in the context of a specific SVT (Storage). -Imagine that you want to turn off the evaluation of some control altogether (regardless of whether people use the `-UseBaselineControls` parameter or not). -Also, for another control, you want people to use a recommendation which leverages an internal tool the security team -in your org has developed. Let us do this for the Storage.json file. Specifically, we will turn off the evaluation -of `Azure_Storage_Audit_Issue_Alert_AuthN_Req` altogether. We will modify severity of -`Azure_Storage_AuthN_Dont_Allow_Anonymous` to `Critical` for our org (it is `High` by default) and -we will change the recommendation people in our org will follow if they need to address an issue with -the `Azure_Storage_Deploy_Use_Geo_Redundant` control. +##### f) Customizing Severity labels +Ability to customize naming of severity levels of controls (e.g., instead of High/Medium, etc. one can now have Important/Moderate, etc.) with the changes reflecting in all avenues (manual scan results/CSV, Log Analytics workspace, compliance summaries, dashboards, etc.) ###### Steps: - - i) Copy the Storage.json from the AzSK installation to your org-policy folder - - ii) Remove everything except the ControlID, the Id and the specific property we want to modify as discussed above. - - iii) Make changes to the properties of the respective controls so that the final JSON looks like the below. + i) Edit the ControlSettings.json file to add a 'ControlSeverity' object as per below: + ```JSON { - "Controls": [ - { - "ControlID": "Azure_Storage_AuthN_Dont_Allow_Anonymous", - "Id": "AzureStorage110", - "ControlSeverity": "Critical" - }, - { - "ControlID": "Azure_Storage_Audit_Issue_Alert_AuthN_Req", - "Id": "AzureStorage120", - "Enabled": false - }, - { - "ControlID": "Azure_Storage_Deploy_Use_Geo_Redundant", - "Id": "AzureStorage130", - "Recommendation": "**Note**: Use our Contoso-IT-EnableGRS.ps1 tool for this!" - } - ] + "ControlSeverity": { + "Critical": "Critical", + "High": "Important", + "Medium": "Moderate", + "Low": "Low" + } } ``` -> Note: The 'Id' field is used for identifying the control for policy merging. We are keeping the 'ControlId' -> field only because of the readability. - - iii) Save the file + ii) Save the file + + iii) Run the policy setup command (the same command you ran for the first-time setup) - iv) Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) + ###### Testing: - It should look something like the below: -```JSON -{ - "OnlinePolicyList" : [ - { - "Name" : "AzSk.json" - }, - { - "Name" : "ControlSettings.json" - }, - { - "Name" : "Storage.json" - } - ] -} -``` +Someone in your org can test this change using the `Get-AzSKAzureServicesSecurityStatus`. You will see that +the controls severity shows as `Important` instead of `High` and `Moderate` instead of `Medium` in the output CSV. - v) Rerun the org policy setup command (the same command you ran for the first time setup) - -###### Testing: -Someone in your org can test this change using the `Get-AzSKAzureServicesSecurityStatus` command on a target -resource group which contains a storage account. If run with the `-UseBaselineControls` switch, you will see that -the anonymous access control shows as `Critical` in the output CSV and the GRS control recommendation has changed to -the custom (internal tool) recommendation you wanted people in your org to follow. The image below shows the CSV file -from a baseline scan after this change: +### Managing policy/advanced policy usage -![Changed Storage controls - Baseline Scan](../Images/07_OrgPolicy_Chg_SVT_JSON.PNG) +#### Downloading and examining policy folder -Likewise, if you run without the `-UseBaselineControls` parameter, you will see that the anon-alert control does not get evaluated and does not -appear in the resulting CSV file. +After installing org policy, you must have observed that the command creates policy folder in local machine with some default folders and files. +If you don't have policies, you can always download them using the following command: -## Using CICD Extension with custom org-policy - -To set up CICD when using custom org-policy, please follow below steps: -1. Add Security Verification Tests (SVTs) in VSTS pipeline by following the main steps [here](../03-Security-In-CICD#adding-svts-in-the-release-pipeline) . -2. Obtain the policy store URl by : - 1. Download the installer file (ps1) from Org specific iwr command.To download file, just open the URL from iwr command. - ``` - E.g.: iwr 'https://azskxxx.blob.core.windows.net/installer/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex - ``` - 2. Open the downloaded file, find the following variable and copy the URL as below. - ``` - [string] $OnlinePolicyStoreUrl = "https://azskxxx.blob.core.windows.net/policies/`$(`$Version)/`$(`$FileName)?sv=2016-05- 31&sr=c&sig=xxx&spr=https&st=2018-01-02T11%3A18%3A37Z&se=2018-07-03T11%3A18%3A37Z&sp=rl" , - ``` -3. Remove the 4 backtick (\`) characters from URL. -``` -E.g. https://azskxxx.blob.core.windows.net/policies/$($Version)/$($FileName)?sv=2016-05-31&sr=c&sig=xxx&spr=https&st=2018-01-02T11%3A18%3A37Z&se=2018-07-03T11%3A18%3A37Z&sp=rl +```PowerShell +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -DownloadPolicy ` + -PolicyFolderPath "D:\ContosoPolicies" ``` -4. Add following variables in the release definition in which ‘AzSK Security Verification Tests’ task is added. - 1. AzSKServerURL = . - 2. EnableServerAuth = false - -Having set the policy URL along with AzSK_SVTs Task, you can verify if your CICD task has been properly setup by following steps [here](../03-Security-In-CICD#verifying-that-the-svts-have-been-added-and-configured-correctly) . -## Next Steps: +These files are uploaded to the policy storage as well. You can recollect the function of each of these files from [here.](Readme.md#basic-files-setup-during-policy-setup) -Once your org policy is setup, all scenarios/use cases of AzSK should work seamlessly with your org policy server -as the policy endpoint for your org (instead of the default CDN endpoint). Basically, you should be able to do one -or more of the following using AzSK: - - People will be able to install AzSK using your special org-specific installer (the 'iwr' install command) - - Developers will be able to run manual scans for security of their subscriptions and resources (GRS, GSS commands) - - Teams will be able to configure the AzSK SVT release task in their CICD pipelines - - Subscription owners will be able to setup Continuous Assurance (CA) from their local machines (**after** they've installed - AzSK using your org-specific 'iwr' installer locally) - - Monitoring teams will be able to setup AzSK OMS view and see scan results from CA (and also manual scans and CICD if configured) - - You will be able to do central governance for your org by leveraging telemetry events that will collect in the master subscription - from all the AzSK activity across your org. +#### Working with ‘local’ mode (policy dev-test-debug) -## Testing and troubleshooting org policy +You can run the scan pointing to the local policy present on your dev box using the following steps. It will enable you test the policy customizations before pushing those to the server. -#### Testing the overall policy setup -The policy setup command is fairly lightweight - both in terms of effort/time and in terms of costs incurred. We recommend that -you set up a 'Staging' environment where you can do all pre-testing of policy setup, policy changes, etc. A limited number of -people could be engaged for testing the actual end user effects of changes before deploying them broadly. -Also, you can choose to retain the staging setup or just re-create a fresh one for each major policy change. +Step 1: Point AzSK settings to local org policy folder("D:\ContosoPolicies\"). + +```PowerShell +Set-AzSKPolicySettings -LocalOrgPolicyFolderPath "D:\ContosoPolicies\" +``` -For your actual (production) policies, we recommend that you check them into source control and use the local close of *that* folder as the location -for the AzSK org policy setup command when uploading to the policy server. In fact, setting things up so that any policy -modifications are pushed to the policy server via a CICD pipeline would be ideal. (That is how we do it at CSE.) +This will update "AzSKSettings.json" file present at location "%LocalAppData%\Microsoft\AzSK" to point to local folder instead of server storage. - -#### Troubleshooting common issues -Here are a few common things that may cause glitches and you should be careful about: +You can run Get-AzSKInfo (GAI) cmdlet to check the current AzSK settings. It will show OnlinePolicyStoreUrl as policyFolder path (instead of the blob URL). -- Make sure you use exact case for file names for various policy files (and the names must match case-and-all -with the entries in the ServerConfigMetadata.json file) -- Make sure that no special/BOM characters get introduced into the policy file text. (The policy upload code does scrub for -a few known cases but we may have missed the odd one.) -- Don't forget to make entries in ServerConfigMetadata.json for all files you have changed. -- Note that the policy upload command always generates a fresh installer.ps1 file for upload. If you want to make changes to + ```PowerShell + GAI -InfoType HostInfo + ``` +![Local Host Settings](../Images/07_OrgPolicy_LocalSettings.PNG) + + +Step 2: Perform the customization to policy files as per scenarios. + +Here you can customize the list of baseline or preview baseline controls for your org using steps already explained [here](Readme.md#d-creating-a-custom-control-baseline-for-your-org) (excluding the last step of running the policy setup or policy update command.) + +Step 3: Now you run scan to see policy updates in effect. Clear session state and run scan commands (GRS or GSS) with parameters sets for which config changes are done like UseBaselineControls,ResourceGroupNames, controlIds etc. + +```PowerShell +# Clear AzSK session cache for settings +Clear-AzSKSessionState + +# Run subscription scan using local policy settings +Get-AzSKSubscriptionSecurityStatus -SubscriptionId + +# Run services security scan with baseline using local policy settings +Get-AzSKAzureServicesSecurityStatus -SubscriptionId -UseBaselineControls +``` + +Step 3: If scan commands are running fine with respect to the changes done to the configuration, you can update policy based on parameter set used during installations. If you see some issue in scan commands, you can fix configurations and repeat step 2. + +```PowerShell +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" + +#If custom resources names are used during setup, you can use below parameters to download policy +Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "Contoso-IT-RG" ` + -StorageAccountName "contosoitsa" ` + -AppInsightName "ContosoITAppInsight" ` + -PolicyFolderPath "D:\ContosoPolicies" +``` + +Step 4: Validate if policy is correctly uploaded and there are no missing mandatory policies using policy health check command + +**Note:** +It is always recommended to validate health of org policy for mandatory configurations and policy schema syntax issues using below command. You can review the failed checks and follow the remedy suggested. + +```PowerShell +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" + +#If you have used customized resource names, you can use below parameter sets to run health check + +Get-AzSKOrganizationPolicyStatus -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "RGName" ` + -StorageAccountName "PolicyStorageAccountName" +``` + +Step 5: If all the above steps works fine, you can point back your AzSK setting to online policy server by running "IWR" command generated at the end of *Update-AzSKOrganizationPolicy* + + +You can also set up a 'Staging' environment where you can do all pre-testing of policy setup, policy changes, etc. A limited number of +people could be engaged in testing the actual end user effects of the policy changes before deploying them for broader usage. +Also, you can choose to retain the staging setup or just re-create a fresh one for each major policy change. + + +For your actual (production) policies, we recommend that you check them into source control and use the local clone of *that* folder as the location +for the AzSK org policy setup command when uploading to the policy server. In fact, setting things up so that any policy +modifications are pushed to the policy server via a CICD pipeline would be ideal. (That is how we do it at CSE.) +Refer [maintaining policy in source-control]() and [deployment using CICD pipeline](). + + +#### Troubleshooting common issues +Here are a few common things that may cause glitches and you should be careful about: + +- Make sure you use exact case for file names for various policy files (and the names must match case-and-all +with the entries in the ServerConfigMetadata.json file) +- Make sure that no special/BOM characters get introduced into the policy file text. (The policy upload code does scrub for +a few known cases, but we may have missed the odd one.) +- Note that the policy upload command always generates a fresh installer.ps1 file for upload. If you want to make changes to that, you may have to keep a separate copy and upload it. (We will revisit this in future sprints.) + + +### How to upgrade org AzSK version to the latest AzSK version + +DevOps kit team releases the newer version of the AzSK module on 15th of every month. It is recommended that you upgrade your org's AzSK version to the latest available version to ensure that your org is up to date with the latest security controls and features. You need to follow the steps below to smoothly upgrade AzSK version for your org: + +1. Install latest AzSK module in your local machine with the help of common setup command + + ```PowerShell + # Use -Force switch as and when required + Install-Module AzSK -Scope CurrentUser -AllowClobber + ``` + +2. Go through the [release notes](https://azsk.azurewebsites.net/ReleaseNotes/LatestReleaseNotes.html) for AzSK latest version. It typically lists the changes which may impact org policy users under section 'Org policy/external user updates'. + +3. If the release notes indicate that you need to perform any additional steps before upgrading the org policy version then perform those changes with the help of [org policy updates page](OrgPolicyUpdate.md). It is highly recommended that you do these changes to your local policy folder and test those before pushing to the policy server. Instructions at [downloading your existing org policies](Readme.md#downloading-and-examining-policy-folder) and [Working with ‘local’ mode (policy dev-test-debug)](Readme.md#working-with-local-mode-policy-dev-test-debug) would be useful to do so. +If there are no additional steps mentioned, then you can go ahead with next step. + +5. Run UOP with AzSK version update flag + + ```PowerShell + # For Basic Setup + Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" -OverrideBaseConfig OrgAzSKVersion + + #For custom Resource Group Setup + Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso-IT" ` + -ResourceGroupName "Contoso-IT-RG" ` + -StorageAccountName "contosoitsa" ` + -PolicyFolderPath "D:\ContosoPolicies" -OverrideBaseConfig OrgAzSKVersion + ``` + + Internally, this will update the AzSK version in the AzSK.Pre.json file present on your org policy server.. + +#### Upgrade scenarios in different scan sources + +Once org policy is updated with the latest AzSK version, you will see it in effect in all environments + + **Local scans:** If application teams are using older version(or any other version than mentioned in org policy), they will start seeing warning as shown below while running scans. + +![Entry in ServerConfigMetadata.json](../Images/07_OrgPolicy_Old_Version_Warning.PNG) + +**Continuous Assurance:** CA will auto-upgrade to latest org version when the next scheduled job runs. You can monitor upgrade status with the help of application insight events. Use below query in org AI + + ``` AI Query +| customEvents +| where timestamp >= ago(6d) +| where name == "Control Scanned" +| where customDimensions.ScanSource =="Runbook" +| where customDimensions.ScannerModuleName == "AzSK" +| summarize arg_max(timestamp, *) by SubId = tostring(customDimensions.SubscriptionId) +| summarize CAModuleVersionSummary= count() by Version = tostring(customDimensions.ScannerVersion) +| render piechart + ``` + + ![CAVersionSummary.json](../Images/07_OrgPolicy_CAVersionSummary.PNG) + + **CICD:** As of now, CICD SVT task does not support version from org policy settings. It always installs latest AzSK version available in PowerShell gallery, irrespective of version mentioned in policy. Although it refers other control policies from policy store. + +### Maintaining policy in source-control + +Coming soon + +### Policy deployment using CICD pipeline + +Coming soon + +# Create security compliance monitoring solutions +Once you have an org policy setup running smoothly with multiple subscriptions across your org, you will need a solution that provides visibility of security compliance for all the subscriptions across your org. This will help you drive compliance/risk governance initiatives for your organization. + +When you setup your org policy endpoint (i.e. policy server), one of the things that happens is creation of an Application Insights workspace for your setup. After that, whenever someone performs an AzSK scan for a subscription that is configured to use your org policy, the scan results are sent (as 'security' telemetry) to your org's Application Insights workspace. Because this workspace receives scan events from all such subscriptions, it can be leveraged to generate aggregate security compliance views for your cloud-based environments. + +## Create cloud security compliance report for your org using PowerBI +We will look at how a PowerBI-based compliance dashboard can be created and deployed in a matter of minutes starting with a template dashboard that ships with the AzSK. All you need apart from the Application Insights instance is a CSV file that provides a mapping of your organization hierarchy to subscription ids (so that we know which team/service group owns each subscription). + +> Note: This is a one-time activity with tremendous leverage as you can use the resulting dashboard (example below) towards driving security governance activities over an extended period at your organization. + +#### Step 0: Pre-requisites +To create, edit and publish your compliance dashboard, you will need to install the latest version of PowerBI desktop on your local machine. Download it from [here](https://powerbi.microsoft.com/en-us/desktop/). + + +#### Step 1: Prepare your org-subscription mapping +In this step you will prepare the data file which will be fed to the PowerBI dashboard creation process as 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/07_OrgPolicy_PBI_OrgMetadata.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. | + +> **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. + + +#### Step 2: Upload your mapping to the Application Insights (AI) workspace + +In this step you will import the data above into the AI workspace created during org policy setup. + + **(a)** Locate the AI resource that was created during org policy setup in your central subscription. This should be present under org policy resource group. After selecting the AI resource, copy the Instrumentation Key. + + **(b)** To push org Mapping details, copy and execute the script available [here](./Scripts/OrgPolicyPushOrgMappingEvents.txt). + + > **Note**: Due to limitation of application insight, you will need to repeat this step every 90 days interval. + +#### Step 3: Create a PowerBI report file +In this section we shall create a PowerBI report locally within PowerBI Desktop using the AI workspace from org policy subscription as the datasource. We will start with a default (out-of-box) PowerBI template and configure it with settings specific to your environment. + +> Note: This step assumes you have completed Step-0 above! + +**(a)** Get the ApplicationId for your AI workspace from the portal as shown below: + +![capture applicationInsights AppId](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_10.PNG) + +**(b)** Download and copy the PowerBI template file from [here](https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/TemplateFiles/AzSKComplianceReport.pbit) to your local machine. + +**(c)** Open the template (.pbit) file using PowerBI Desktop, provide the AI ApplicationId and click on 'Load' as shown below: + +![capture applicationInsights AppId](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_11.PNG) + +**(d)** PowerBI will prompt you to login to the org policy subscription at this stage. Authenticate using your user account. (This step basically allows PowerBI to import the data from AI into the PowerBI Desktop workspace.) +![Login to AI](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_12.PNG) + +Once you have successfully logged in, you will see the AI data in the PowerBI report along with org mapping as shown below: + +![Compliance summary](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_13.PNG) + +The report contains 2 tabs. There is an overall/summary view of compliance and a detailed view which can be used to see control 'pass/fail' details for individual subscriptions. An example of the second view is shown below: + +![Compliance summary](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_14.PNG) + +> TBD: Need to add steps to control access to the detailed view by business group. (Dashboard RBAC.) + +#### Step 4: Publish the PowerBI report to your enterprise PowerBI workspace + +**(a)** Before publishing to the enterprise PowerBI instance, we need to update AI connection string across data tables in the PowerBI report. The steps to do this are as below: + +[a1] Click on "Edit Queries" menu option. + +![Update AI Connection String](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_15.PNG) + +[a2] Copy the value of "AzSKAIConnectionString" + +![Update AI Connection String](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_16.PNG) + +[a3] Replace the value of "AzSKAIConnectionString" with the actual connection string (e.g., AzSKAIConnectionString => "https://api.applicationinsights.io/v1/apps/[AIAppID]/query"). You should retain the "" quotes in the connection string. + +![Update AI Connection String](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_17.PNG) + +[a4] Repeat this operation for ControlResults_AI, Subscriptions_AI, and ResourceInventory_AI data tables. + +[a5] Click on "Close and Apply". + +**(b)** You can now publish your PBIX report to your workspace. The PBIX file gets created locally when you click "Publish". + +Click on Publish + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_18.PNG) + +Select destination workspace + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_19.PNG) + +Click on "Open [Report Name] in Power BI" + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_21.png) + +**(c)** Now report got published successfully. You can schedule refresh for report with below steps + +Go to Workspace --> Datasets --> Click on "..." --> Click on "Schedule Refresh" + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_22.png) + +Click on "Edit credentials" + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_25.png) + +Sign in with account with which policy is created + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_26.png) + +Add refresh scheduling timings and click on "Apply" + +> **Note:** You may not see "Schedule refresh" option if step [a3] and [a4] is not completed successfully. + +![Publish PBIX report](../Images/07_OrgPolicy_PBI_OrgMetadata_AI_24.png) + + + +## AzSK org health monitoring dashboard + +Monitoring dashboard gets created along with policy setup and it lets you monitor the operations for various DevOps Kit workflows at your org.(e.g. CA issues, anomalous control drifts, evaluation errors, etc.). + +You will be able to see the dashboard at the home page of Azure Portal. If not, you can navigate to the following path to see the dashboard + +Go to Azure Portal --> Select "Browse all dashboards" in dashboard dropdown --> Select type "Shared Dashboard" --> Select subscription where policy is setup -->Select "DevOps Kit Monitoring Dashboard [OrgName]" + +Below is snapshot of the dashboard +Effective org Policy Evaluation + +## Detail resource inventory dashboard + +With the help of telemetry events you will be able to monitor resources inventory in the Org. This will give the visibility over all resources along with control failures over all subscriptions. The PowerBI based template will be shared soon + +# Compliance notifications + +## Compliance notification to subscription owners + +Coming soon + +# Advanced usage of org policy (extending AzSK) + +## Customizing the SVTs + + + It is powerful capability of AzSK to enable an org to customize the SVT behaviour. Refer [extending AzSK modules](./Extending%20AzSK%20Module/Readme.md) for more details. You will be able to achieve the following scenarios. + + - [Update/extend existing control by augmenting logic](./Extending%20AzSK%20Module/Readme.md##steps-to-extend-the-control-svt) + - [Add new control for existing GSS/GRS SVT](./Extending%20AzSK%20Module/Readme.md#a-extending-a-gss-svt) + - [Add an altogether new SVT (non-existing service scan)](./Extending%20AzSK%20Module/Readme.md#steps-to-add-a-new-svt-to-the-azsk-module) + + + +## Customizing subscription security + Along with subscription security checks, AzSK provides security provisioning commands (e.g. setting up mandatory ARM policies, RBAC roles, ASC configurations etc.) on a subscription. Refer [link](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-subscription-security-provisioning-1) for more details on provisioning commands. Each provisioning status is validated with the help of subscription scan controls. Below table gives the details of provisioning commands , GSS control to validate provisioning status and policy file name where all provisioning configurations are present. + +| Component | Provisioning Command | Control in GSS | Policy File Name | Description | +| ---- | ---- | ---- |---- | ---- | +| ARM Policy | Set-AzSKARMPolicies | Azure_Subscription_Config_ARM_Policy | Subscription.ARMPolicies.json | Sets ARM policies corresponding to certain actions that are considered insecure. | +| Critical Alerts | Set-AzSKAlerts | Azure_Subscription_Audit_Configure_Critical_Alerts | Subscription.InsARMAlerts.json | Configuration of subscription and resource alerts for activities with significant security implications | +| Azure Security Center configuration | Set-AzSKAzureSecurityCenterPolicies | Azure_Subscription_Config_Azure_Security_Center | SecurityCenter.json | Default enterprise policy settings for Azure Security Center like configuring security contact information in ASC etc. | +| RBAC roles/permissions | Set-AzSKSubscriptionRBAC | Azure_Subscription_AuthZ_Add_Required_Central_Accounts | Subscription.RBAC.json | Setup mandatory accounts that are required for central scanning/audit/compliance functions. | + +Common steps for configuring policies for subscription provisioning + + i) Copy the provisioning policy file from the AzSK installation folder (%userprofile%\documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\SubscriptionSecurity) to your org-policy folder + + ii) Edit policy file with schema and guidance given below section for each component + + iii) Add entry for configuration in index file (ServerConfigMetadata.json) with OverrideOffline property. OverrideOffline is required for all provisioning policies as it does not support overlay method. + +![Override Configurations](../Images/07_OrgPolicy_PovisioningPolicy.PNG) + + iv) Rerun the org policy update or setup command (the same command you ran for the first-time setup) + + +Once policy is updated, it will start respecting in subscription scan command and failing controls with details of missing configuration on subscriptions. +Ideally below steps are expected to be executed by individual subscription owners. + + i) Run subscription scan + + ```PowerShell + # Subscription scan + Get-AzSKSubscriptionSecurityStatus -SubscriptionId + # Scanning perticular policy control + Get-AzSKSubscriptionSecurityStatus -SubscriptionId -ControlIds "Azure_Subscription_Config_ARM_Policy" + ``` + +ii) Validate detail logs printing missing policies expected by Org policy + +iii) Execute [provisioning command](../01-Subscription-Security/Readme.md#azsk-subscription-security-provisioning-1) with required parameters + + > **Note:** If you want to configure all policies(alert,ARM policy, ASC and RBAC), you can use all in one command Set-AzSKSubscriptionSecurity. + +iv) Run subscription scan again and validate control gets passed. + + +### Schema for policy files +#### ARM policy + + ```C# + { + "Version": "3.1809.0", + "Policies": [ + { + "policyDefinitionName": "AzSK_ARMPol_Deny_Classic_Resource_Create", // Friendly policy name. The format used is AzSK_ARMPol___ + "policyDefinition": "{\"if\":{\"anyOf\":[{\"field\":\"type\",\"like\":\"Microsoft.ClassicCompute/*\"},{\"field\":\"type\",\"like\":\"microsoft.classicStorage/*\"},{\"field\":\"type\",\"like\":\"Microsoft.ClassicNetwork/*\"}]},\"then\":{\"effect\":\"deny\"}}", // Policy definition. Here we are defining denial of classic resource creation + "description": "Policy to deny upon creation of classic/v1 (i.e., ASM-based) resources", // Description about the policy + "tags": [ + "Mandatory" + ], // Tag for policy. Mandatory tag is always picked up by set-AzSKARMPolicy command. If you mention any other tags, you will need to pass explicitly to set command + "enabled": true, // Defines whether the ARM policy is enabled or not. + "scope": "/subscriptions/$subscriptionId" // Scope at which policy needs to be applied + } + ], + "DeprecatedPolicies" : [] // Array of deprecated policydefinitionnames. This policy will get removed during policy setup + } + ``` + +To view the samples of ARM policy definitions rules and syntaxes, refer [link](https://docs.microsoft.com/en-us/azure/governance/policy/samples/) + +#### Alert set +You will find current supported alert list [here](/02-Secure-Development/ControlCoverage/Feature/AlertList.md). + + ```C# + { + "Version": "3.1803.0", + "AlertList": [ + { + "Name": "AzSK_Subscription_Alert", // Alert name containing group of all operations. + "Description": "Alerts for Subscription Activities", // Alert description + "Enabled": true, // Defines alert is enabled or not + "Tags": [ + "Mandatory" + ], // Tag for Alerts group. Mandatory tag is always picked up by set-AzSKAlerts command. + "AlertOperationList": [ + { + "Name": "AzSK_Assign_the_caller_to_User_Access_Administrator_role", // Friendly name for operations + "Description": "Grants the caller User Access Administrator access at the tenant scope", // operation details + "OperationName": "Microsoft.Authorization/elevateAccess/action", // operation name + "Tags": [ + "Mandatory" + ], + "Severity": "Critical", // severity for operation Critial/High. Critical operations are considered for SMS alerts + "Enabled": true // // Defines operation is enabled or not + } + ] + } + } + ``` +You will get all activity operations that can be added as part of alert using below command + +```PowerShell +Get-AzProviderOperation | FT +``` + +#### Security center configurations + + Security center can be configured for three things + + - Autoprovisioning + - SecurityContacts + - Default policy setup + +```C# +{ + "Version": "3.1906.0", + "autoProvisioning" : { + "id": "/subscriptions/{0}/providers/Microsoft.Security/autoProvisioningSettings/default", + "name": "default", + "type": "Microsoft.Security/autoProvisioningSettings", + "properties": { + "autoProvision": "On" + } + }, + "securityContacts" : { + "id": "/subscriptions/{0}/providers//Microsoft.Security/securityContact/default", + "name": "default", + "type": "Microsoft.Security/securityContact", + "properties": { + "alertNotifications": { + "state": "On", + "minimalSeverity": "Medium" + }, + "emails": "{1}", + "notificationsByRole": { + "state": "On", + "roles": [ + "Owner", + "ServiceAdmin" + ] + }, + "phone": "{2}" + } + }, + "policySettings" : { + "properties": { + "displayName": "ASC Default (subscription: {0})", + "policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8", + "scope": "/subscriptions/{0}", + "notScopes": [], + "parameters": { + "endpointProtectionMonitoringEffect": { + "value": "AuditIfNotExists" + } + }, + "description": "This policy assignment was automatically created by Azure Security Center", + "metadata": { + "assignedBy": "Security Center" + } + }, + "id": "/subscriptions/{0}/providers/Microsoft.Authorization/policyAsssignments/SecurityCenterBuiltIn", + "type": "Microsoft.Authorization/policyAssignments", + "name": "SecurityCenterBuiltIn" + }, + "optionalPolicySettings" : {} +} +``` + + ### RBAC mandatory/deprecated lists + + You will be able to check/configure mandatory and deprecated list of RBAC for all subscriptions with the help of below schema + + ```C# + { + "ActiveCentralAccountsVersion": "2.1709.0", + "DeprecatedAccountsVersion": "2.1709.0", + "ValidActiveAccounts": [ + { + "Name": "Contoso Cost Trackers", // Name of the account to be provisioned or checked for. + "Description": "This AAD group account is deployed as Reader on all subscriptions at Contoso to monitor cost.", //Description for your account. + "ObjectId": "", // Object id for user or group or SPN in tenant + "ObjectType": "Group", // ServicePrincipal or User or Group. + "RoleDefinitionName": "Reader", //Subscription RBAC rolename. + "Scope": "/subscriptions/$subscriptionId", //Scope of access. + "Type": "Provision or Validate. E.g., Provision", + "Tags": [ "Mandatory" ], //Commma separated list of tags each in double quotes. The tag 'Mandatory' means this account is deployed by default and always checked during verification. + "Enabled": true + } + ], + "DeprecatedAccounts": [ + { + "Name": "Name of the account that is considered deprecated and must be deprovisioned. E.g., AutoDeploySPN", + "Description": "Description for the account. E.g., This was used for automated deployments in the past. It must be removed from all subscriptions.", + "ObjectId": "object_id_for_user_or_group_or_SPN_in_tenant", + "ObjectType": "ServicePrincipal or User or Group, E.g., ServicePrincipal", + "Enabled": false + } + ] + } +``` + +## ARM checker policy customization + +Check [this](https://github.com/azsk/DevOpsKit-docs/blob/master/03-Security-In-CICD/Readme.md#extending-arm-template-checker-for-your-organization) + + +## Change default resource group name (AzSKRG) and location (EastUS2) created for AzSK components +You can control default resource group name and location using AzSK config present in org policy. Follow below steps to override default behaviour. + +> **Note:** Changing default resource group name will break existing continuous assurance setup. You will need to do re-setup of all CA. + +**Steps:** + +i) Open the AzSK.json from your local org-policy folder + +ii) Add the properties for as under: + + "AzSKRGName" : "", + "AzSKLocation" : "" + +iii) Save the file + +iv) Run the policy update command. + + +##### Testing: + +Run "IWR" in a fresh PS session (you can ask any other user to run this IWR) to setup policy setting in local. If you have already installed policy using IWR, just run CSS (Clear-AzSKSessionState) followed by command *Set-AzSKSubscriptionSecurity* with required parameters as per the [doc](../01-Subscription-Security/Readme.md#azsk-subscription-security-provisioning-1). This will provision AzSK components(Alerts/Storage etc) under new resource group and location. + +**Note:** For continuous assurance setup, you need to follow two extra steps. + +i) Pass location parameter "AutomationAccountLocation" explicitly during execution of installation command (Install-AzSKContinuousAssurance). + +ii) Update $StorageAccountRG variable (In RunbookScanAgent.ps1 file present in policy store) value to AzSKRGName value. + + +## Scenarios for modifying ScanAgent + + ### Scanning only baseline controls using continuous assurance setup + + Continuous Assurance (CA) is configured to scan all the controls. We have kept this as a default behavior since org users often tend to miss out on configuring baseline controls. This behavior is controlled from org policy. + If you observed, there are two files present in policy folder under **CA-Runbook** folder, + + - RunbookCoreSetup.ps1: Responsible to install AzSK module + - RunbookScanAgent.ps1: Performs CA scans and export results to storage account + + If you open RunbookScanAgent and search for the scan command text Get-AzSKAzureServicesSecurityStatus and Get-AzSKSubscriptionSecurityStatus, you will find it is scanning for all controls excluding "OwnerAccess" control. This is due to the CA SPN having limited (reader) permissions on the subscription. + To make CA scan only thr baseline controls, append parameter '-UseBaselineControls' to these scan commands. + + Follow the same steps as earlier to publish these files to org policy server. + + After policy update, CA will start scanning only the baseline controls. + + ### Scanning owner and graph access controls using CA + + During CA setup, SPN is assigned with minimum privileges i.e. reader access on subscription and contributor access on AzSKRG. As a reader, it will not be able to scan controls requiring owner or graph read permissions. You can elevate SPN permission to 'Owner' and remove '-ExcludeTags "OwnerAccess"' parameter against the scan commands in above 2 files. As always, follow the same steps tp publish these files to org policy server. + However, in general we let SPN have minimum permissions assigned and make it a practice for individual teams to perform scan with high privileged role on regular basis to validate Owner access controls. + + ### Reporting critical alerts + + Comming soon + + + +# Org policy usage statistics and monitoring using telemetry + +The telemetry data can be leveraged by org policy owners to understand AzSK usage, monitor compliance drift, CA health, resource inventory, troubleshooting etc. All helpful AI queries are listed on page [here](https://github.com/azsk/DevOpsKit-docs/tree/master/06-Security-Telemetry/App-Insights-Queries). + +## Frequently Asked Questions + +#### I am getting exception "The current subscription has been configured with DevOps kit policy for the '***' Org, However the DevOps kit command is running with a different ('org-neutral') org policy....."? + +When your subscription is running under org policy, AzSK marks subscription for that Org. If user is running scan commands on that subscription using Org-neutral policy, it will block those commands as that scan/updates can give invalid results against org policy. You may face this issue in different environments. Below steps will help you to fix issue + +**Local Machine:** + +- Run “**IWR**" installation command shared by Policy Owner. This will ensure latest version installed with org policy settings.(**Note:** If you are from CSE, please install the AzSK via instructions at https://aka.ms/devopskit/onboarding so that CSE-specific policies are configured for your installation.) + +- Run "*Clear-AzSKSessionState*" followed by any scan command and validate its running with org policy. It gets displayed at the start of command execution "Running AzSK cmdlet using ***** policy" + +**Continuous Assurance:** + +- Run "*Update-AzSKContinuousAssurance*" command with org policy. This will ensure that continuous assurance setup is configured with org policy settings. + +- After above step, you can trigger runbook and ensure that after job completion, scan exported in storage account are with org policy. You can download logs and validate it in file under path /ETC/PowerShellOutput.LOG. +Check for message during start of command "Running AzSK cmdlet using ***** policy" + + +**CICD:** +- You need to configure policy url in pipeline using step **5** defined [here](https://github.com/azsk/DevOpsKit-docs/tree/master/03-Security-In-CICD#adding-svts-in-the-release-pipeline) + +- Make sure that the variables you have configured have correct names and values. You may refer [this table.](https://github.com/azsk/DevOpsKit-docs/blob/master/03-Security-In-CICD/Readme.md#advanced-cicd-scanning-capabilities) + +- To validate if pipeline AzSK task is running with org policy. You can download release logs from pipeline. Expand "AzSK_Logs.zip" --> Open file under path "/ETC/PowerShellOutput.LOG" --> Check for message at the start of command execution "Running AzSK cmdlet using ***** policy" + + +If you want to run commands with Org-neutral policy only, you can delete tag (AzSKOrgName_{OrgName}) present on AzSKRG and run the commands. + +If you are maintaining multiple org policies and you want to switch scan from one policy to other, you can run Set/Update commands with '-Force' flag using policy you wanted to switch. + +#### Latest AzSK is available but our org CA are running with older version? + +AzSK keeps on adding and enhancing features with different capabilities to monitor Security compliance for org subscriptions. During these enhancement in new releases, it may include latest features and some breaking changes. To provide smoother upgrade and avoid policy breaks, AzSK provides feature for org policy to run AzSK with specific version by using configuration present in AzSK.Pre.json. This configuration is referred in multiple places for installing org supported AzSK version in different environments like Installer (IWR) (Installs AzSK in local machine), RunbookCoreSetup (Install AzSK in CA). You need to update property "CurrentVersionForOrg" in AzSK.Pre.json to latest available version after validating if org policy is compatible with latest AzSK version. + + +#### We have configured baseline controls using ControlSettings.json on Policy Store, But Continuous Assurance (CA) is scanning all SVT controls on subscription? + +Continuous Assurance (CA) is configured to scan all the controls. We have kept this as a default behavior since org users often tend to miss out on configuring baseline controls. This behavior is controlled from org policy. If you observed, there are two files present in policy store, RunbookCoreSetup.ps1 (Responsible to install AzSK) and RunbookScanAgent.ps1 (Performs CA scans and export results to storage account). You can update RunbookScanAgent to make only baseline scan. (By passing -UseBaselineControls parameter to Get-AzSKAzureServicesSecurityStatus and Get-AzSKSubscriptionSecurityStatus commands present in RunbookScanAgent.ps1 file). + +#### Continuous Assurance (CA) is scanning less number of controls as compared with manual scan? + CA automation account runs with minimum privileges i.e. 'Reader' RBAC permission and cannot scan some controls that require more access. + Here are a few examples of controls that CA cannot fully scan or can only 'partially' infer compliance for: + +Azure_Subscription_AuthZ_Dont_Use_NonAD_Identities - requires Graph API access to determine if an AAD object is an 'external' identity + +Azure_Subscription_AuthZ_Remove_Management_Certs - querying for management certs requires Co-Admin permission + +Azure_AppService_AuthN_Use_AAD_for_Client_AuthN - often this is implemented in code, so an app owner has to attest this control. Also, any 'security-related' config info is not accessible to the 'Reader' RBAC role. + +Azure_CloudService_SI_Enable_AntiMalware - needs co-admin access + +Azure_CloudService_AuthN_Use_AAD_for_Client_AuthN - no API available to check this (has to be manually attested) + +Azure_Storage_AuthN_Dont_Allow_Anonymous - needs 'data plane' access to storage account (CA SPN being a 'Reader' cannot do 'ListKeys' to access actual data). + +In general, we make practice to individual teams to perform scan with high privileged role on regular basis to validate Owner access controls results. If you wanted to scan all controls using continuous assurance, you have to + +- Provide CA SPN's as [Owner/Co-Admin RBAC role](https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal#grant-access) at subscription scope and [graph API read permissions](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications#updating-an-application). + +- Remove *-ExcludeTags "OwnerAccess"* parameter against scan commands (*Get-AzSKAzureServicesSecurityStatus* and *Get-AzSKSubscriptionSecurityStatus*) present in RunbookScanAgent.ps1 file on policy store. + +#### How should I protect org policy with AAD based auth? + +Currently basic org policy setup uses read only SAS token to fetch policy files. You will be able to protect policy based on AAD auth using below steps + +1. Setup AAD based API: + + Create API Service with [AAD auth](https://docs.microsoft.com/en-us/azure/app-service/app-service-mobile-how-to-configure-active-directory-authentication) which will point to and return files from Policy container present under org policy Store. API URL looks like below + + ``` + https://.azurewebsites.net/api/files?version=$Version&fileName=$FileName + ``` + +> **Note:** Here version and file name are dynamic and passed during execution of AzSK commands. + +2. Update Installer(IWR) with latest policy store url: + + Go to IWR file location(present in policy store --> installer + --> AzSK-EasyInstaller.ps1) + + a. Update OnlinePolicyStoreUrl with AD based auth API URL from step 1. (**Note:** Keep tilt(\`) escape character as is) + + https://.azurewebsites.net/api/files?version=`$Version&fileName=`$FileName + + b. Search for command "Set-AzSKPolicySettings" in IWR and add parameter "-EnableAADAuthForOnlinePolicyStore" + +3. Update local settings to point to latest API: + + Run IWR command in local machine PowerShell. This will point your local machine to latest policy store URL and AzSK commands will start using AAD based auth. + +4. Update existing CA to point to latest API: + + If CA is already installed on subscriptions. You can just run Update-CA command. This will update runbook to use latest policy store URL. + +5. Update CICD task to point to latest API: + + Refer [step 5](https://github.com/azsk/DevOpsKit-docs/tree/master/03-Security-In-CICD#adding-svts-in-the-release-pipeline) from SVT Task documentation to update policy url in pipeline. Make sure you set EnableServerAuth variable to true. + +**Note:** We are already exploring on latest AAD based auth feature available on Storage to protect policy. Above steps will be updated in future once AzSK is compatible with latest features. + +#### Can I completely override policy. I do not want policy to be run in Overlay method? + +Yes. You can completely override policy configuration with the help index file. + +**Steps:** + +i) Copy local version of configuration file to policy folder. Here we will copy complete AppService.json. + +Source location: "%userprofile%\Documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\SVT" + +Destination location: + "D:\ContosoPolicies" +![Copy Configurations](../Images/07_OrgPolicy_CopyConfiguration.png) + + +ii) Update configurations for all required controls in AppService.json + +iii) Add entry for configuration in index file(ServerConfigMetadata.json) with OverrideOffline property + +![Override Configurations](../Images/07_OrgPolicy_ServerConfigOverride.png) + +iv) Run update/install org policy command with required parameters. + +### Control is getting scanned even though it has been removed from my custom org-policy. + +If you want only the controls which are present on your custom org-policy to be scanned, set the OverrideOffline flag to true in the ServerConfigMetadata.json file. + +Example: If you want to scan only the ARMControls present in your org-policy, then set the OverrideOffline flag to true as shown below. + +![ARM Controls override](../Images/07_Custom_Policy_ARMControls.png) + +##### Testing: + +Run clear session state command(Clear-AzSKSessionState) followed by services scan (Get-AzSKAzureServicesSecurityStatus). Scan should reflect configuration changes done. + + + +### How to customize attestation expiry period for controls? + +There are two methods with which attestation expiry period can be controlled using org policy. + +1. Update attestation expiry period for control severity + +2. Update attestation expiry period for a particular control in SVT + +**Note:** Expiry period can be customized only for statuses "WillNotFix", "WillFixLater" and "StateConfirmed". For status "NotAnIssue" and "NotApplicable", expiry period can be customized using "Default" period present as part of ControlSettings configuration. + +#### 1. Update attestation expiry period for control severity + + Steps: + + i) Go to ControlSettings configuration present in module folder. + + Source location: "%userprofile%\Documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\SVT\ControlSettings.json" + + ii) Copy "AttestationExpiryPeriodInDays" settings + + iii) Create/update "ControlSettings.json" in org policy configuration folder (It is the same folder from where org policy is installed) and paste AttestationExpiryPeriodInDays configurations to file + + + iv) Update attestation expiry period against control severity. For e.g., here we will make "High" severity control to expire after 60 days, "Critical" to 15 days and others set to 90 days + + ![Controls attestation expiry override](../Images/07_OrgPolicy_AttestationExpiryOverride.png) + + v) Update org policy with the help of Update-AzSKOrganizationPolicy (UOP) cmdlet. (If you have created policy custom resources, mention resource names as parameter for UOP cmdlet) + + ``` + Update-AzSKOrganizationPolicy -SubscriptionId $SubId -OrgName "Contoso" -DepartmentName "IT" -PolicyFolderPath "D:\ContosoPolicies" + ``` + +##### Testing: + +1. Run clear session state command (Clear-AzSKSessionState). + +2. You can attest one of the "High" severity controls or if you have control already attested, you can go to step 3 + + Example: In this example, we will attest storage control with "WillNotFix" status + + ``` + Get-AzSKAzureServicesSecurityStatus -SubscriptionId $SubId ` + -ResourceNames azskpreviewcontosopr3sa ` + -ControlIds "Azure_Storage_AuthN_Dont_Allow_Anonymous" ` + -ControlsToAttest NotAttested + ``` + + Output: + ![Controls attestation expiry override](../Images/07_OrgPolicy_AttestationFlow.png) + +3. Run Get-AzSKInfo (GAI) cmdlet to get all attested controls in Sub with expiry details. + + Note: Make sure cmdlet is running with org policy. If not you will need to run "IWR" generated at the time of IOP or UOP cmdlet. + + ``` + Get-AzSKInfo -InfoType AttestationInfo -SubscriptionId + ``` + +4. Open CSV or detailed log file generated at the end of command execution. It will show expiry period column for attested column. + + Detailed log: + ![Controls attestation expiry override](../Images/07_Custom_Policy_AttestationExpiryReportOutput.png) + + CSV report: + ![Controls attestation expiry override](../Images/07_Custom_Policy_AttestationExpiryReport.png) + + + +#### 2. Update attestation expiry period for particular control in SVT + + +i) Copy the Storage.json from the AzSK module to your org-policy folder + + Source location: "%userprofile%\Documents\WindowsPowerShell\Modules\AzSK\\Framework\Configurations\SVT\Services\Storage.json" + + Destination location: Policy config folder in local (D:\ContosoPolicies\Config) + +ii) Remove everything except the ControlID, the Id and add property "AttestationExpiryPeriodInDays" as shown below. + + ``` + { + "Controls": [ + { + "ControlID": "Azure_Storage_AuthN_Dont_Allow_Anonymous", + "Id": "AzureStorage110", + "AttestationExpiryPeriodInDays": 45 + } + ] + } + ``` + +iii) Update org policy with the help of UOP cmdlet with required parameters. + + ``` + Update-AzSKOrganizationPolicy -SubscriptionId $SubId -OrgName "Contoso" -DepartmentName "IT" -PolicyFolderPath "D:\ContosoPolicies" + ``` + +##### Testing: + + For testing follow same steps mentioned above for [scenario 1](./#testing-7) + +### How to configure non-AAD identity providers for AppService? + You will be able to configure non-AAD identity providers and external redirect URLs using below settings: + +i)Copy the ControlSettings.json from the AzSK installation to your org-policy folder. + +ii)Update required values in below tags under AppService: +```JSON +"AllowedAuthenticationProviders": [ + ], +"AllowedExternalRedirectURLs": [ + ] +``` + +iii)Make sure identity providers from AllowedAuthenticationProviders are removed from NonAADAuthProperties. +```JSON +"NonAADAuthProperties": [ + "googleClientId", + "facebookAppId" + "twitterConsumerKey", + "microsoftAccountClientId" + ] +``` + +iv) Save the file. + +v) Override ControlSettings.json in ServerConfigMetaData.json as shown below: + +```JSON + { + "OnlinePolicyList" : [ + { + "Name" : "AzSK.json" + }, + { + "Name" : "ControlSettings.json", + "OverrideOffline" :true + }, + { + "Name" : "ServerConfigMetadata.json", + "OverrideOffline" : true + } + ] +} +``` + +vi) Rerun the policy update or setup command (the same command you ran for the first-time setup). + +### How can we treat each public IP address as an individual resource? + Org policy admins can enable public IP address as an individual resource by making following org policy settings: + +i) Copy the ControlSettings.json from the AzSK installation to your org-policy folder. + + a) If you already have a overridden ControlSettings.json, add the following new settings to it. + ```JSON +"PublicIpAddress": { + "EnablePublicIpResource": false + }, +``` + +ii) Update the EnablePublicIpResource setting to true. +```JSON +"PublicIpAddress": { + "EnablePublicIpResource": true + }, +``` + +iii) Save the file. + +iv) Edit the ServerConfigMetadata.json file in your local org-policy folder and create an entry for "ControlSettings.json" as below: + +```JSON + { + "OnlinePolicyList" : [ + { + "Name" : "AzSK.json" + }, + { + "Name" : "ControlSettings.json", + }, + ] +} +``` +v) If you are using an already overridden ControlSettings.json, edit the ServerConfigMetadata.json file as follows: + +```JSON + { + "OnlinePolicyList" : [ + { + "Name" : "AzSK.json" + }, + { + "Name" : "ControlSettings.json", + "OverrideOffline" : true + }, + ] +} +``` + +vi) Rerun the policy update or setup command (the same command you ran for the first-time setup). + +vii) Command that will be helpful in scanning a public IP address resource: + +```PowerShell + $subscriptionId = +$resourceGroupName = +$resourceName = +$ControlId = 'Azure_PublicIpAddress_Justify_PublicIp' +Get-AzSKAzureServicesSecurityStatus -SubscriptionId $subscriptionId ` + -ResourceGroupNames $resourceGroupName ` + -ResourceName $resourceName ` + -ControlId $ControlId + ``` + + + + + + + + + + + diff --git a/07-Customizing-AzSK-for-your-Org/Samples/AddPreviewBaseline/ControlSettings.json b/07-Customizing-AzSK-for-your-Org/Samples/AddPreviewBaseline/ControlSettings.json new file mode 100644 index 00000000..38dfcd64 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/AddPreviewBaseline/ControlSettings.json @@ -0,0 +1,20 @@ +{"PreviewBaselineControls": { + "ResourceTypeControlIdMappingList": [ + { + "ResourceType": "Storage", + "ControlIds": [ + "Azure_Storage_DP_Rotate_Keys" + ] + }, + { + "ResourceType": "AppService", + "ControlIds": [ + "Azure_AppService_DP_Use_Approved_TLS_Version" + ] + } + ], + "SubscriptionControlIdList": [ + "Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access" + ] + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/EditBaseline/ControlSettings.json b/07-Customizing-AzSK-for-your-Org/Samples/EditBaseline/ControlSettings.json new file mode 100644 index 00000000..18e28443 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/EditBaseline/ControlSettings.json @@ -0,0 +1,25 @@ +{ + "NoOfApprovedAdmins": 2, + "BaselineControls": { + "ResourceTypeControlIdMappingList": [ + { + "ResourceType": "AppService", + "ControlIds": [ + "Azure_AppService_DP_Dont_Allow_HTTP_Access", + "Azure_AppService_AuthN_Use_AAD_for_Client_AuthN" + ] + }, + { + "ResourceType": "Storage", + "ControlIds": [ + "Azure_Storage_AuthN_Dont_Allow_Anonymous", + "Azure_Storage_DP_Encrypt_In_Transit" + ] + } + ], + "SubscriptionControlIdList": [ + "Azure_Subscription_AuthZ_Limit_Admin_Owner_Count", + "Azure_Subscription_AuthZ_Dont_Use_NonAD_Identities" + ] + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/EditSVTControl/SubscriptionCore.json b/07-Customizing-AzSK-for-your-Org/Samples/EditSVTControl/SubscriptionCore.json new file mode 100644 index 00000000..dc4612a3 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/EditSVTControl/SubscriptionCore.json @@ -0,0 +1,13 @@ +{ + "FeatureName": "SubscriptionCore", + "Reference": "aka.ms/azsktcp/sshealth", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Subscription_AuthZ_Limit_Admin_Owner_Count", + "Description": "You *must* minimize the number of admins/owners", + "ControlSeverity": "High", + "Id": "SubscriptionCore110" + } + ] +} diff --git a/07-Customizing-AzSK-for-your-Org/Samples/EditSeverityLabel/ControlSettings.json b/07-Customizing-AzSK-for-your-Org/Samples/EditSeverityLabel/ControlSettings.json new file mode 100644 index 00000000..5fe983fa --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/EditSeverityLabel/ControlSettings.json @@ -0,0 +1,5 @@ +{ + "ControlSeverity": { + "Critical": "FixItNow" + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/ControlSettings.json b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/ControlSettings.json new file mode 100644 index 00000000..19a77cd3 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/ControlSettings.json @@ -0,0 +1,5 @@ +{ +"Storage": { + "HttpsExemptedRegion": "southeastasia" + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.json b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.json new file mode 100644 index 00000000..c0dd6fe7 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.json @@ -0,0 +1,11 @@ +{ + "FeatureName": "Storage", + + "Controls": [ + { + "ControlID": "Azure_Storage_DP_Encrypt_In_Transit", + "Id": "AzureStorage160", + "MethodName": "CheckStorageEncryptionInTransitExt" + } + ] +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.ps1 new file mode 100644 index 00000000..de45703a --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/Storage.ext.ps1 @@ -0,0 +1,36 @@ +using namespace Microsoft.Azure.Management.Storage.Models +using namespace Microsoft.WindowsAzure.Storage.Shared.Protocol +Set-StrictMode -Version Latest +class StorageExt: Storage +{ + + StorageExt([string] $subscriptionId, [string] $resourceGroupName, [string] $resourceName): + Base($subscriptionId, $resourceGroupName, $resourceName) + { + } + + StorageExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + } + + hidden [ControlResult] CheckStorageEncryptionInTransitExt([ControlResult] $controlResult) + { + $stgAcctName = $this.ResourceContext.ResourceName + # Call the default implementation to get the actual status. + $controlResult = $this.CheckStorageEncryptionInTransit($controlResult) + $exemptedRegion = $($this.ControlSettings.Storage.HttpsExemptedRegion) + $encryptionEnabled = ($controlResult.VerificationResult -eq [VerificationResult]::Passed) + # 'Exempt' the account if it belongs to the exempted region... + if($this.ResourceObject.Location -eq $exemptedRegion) + { + $controlResult.AddMessage("Note: Storage account [$stgAcctName] has EnableHttps set to: $encryptionEnabled.`nAccounts in the region [$exemptedRegion] are not required to enable encryption. Control result overridden as [Passed]"); + $controlResult.VerificationResult = [VerificationResult]::Passed + } + else + { + $controlResult.AddMessage("Note: Storage account [$stgAcctName] has EnableHttps set to: $encryptionEnabled.`nThis account is not in the exempted region [$exemptedRegion]. Default AzSK control result applies to it!"); + } + return $controlResult; + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/ControlSettings.json b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/ControlSettings.json new file mode 100644 index 00000000..231d035a --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/ControlSettings.json @@ -0,0 +1,5 @@ +{ +"Storage": { + "RequiredRegion": "eastus2" + } +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.json b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.json new file mode 100644 index 00000000..a9dec3d1 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.json @@ -0,0 +1,29 @@ +{ + "FeatureName": "Storage", + "Reference": "aka.ms/azsktcp/storage", + "IsMaintenanceMode": false, + "Controls": [ + { + "ControlID": "Azure_Storage_Create_In_Approved_Regions", + "Description": "Create storage accounts only in org-approved region: [$($this.ControlSettings.Storage.RequiredRegion)].", + "Id": "AzureStorage910", + "ControlSeverity": "High", + "Automated": "Yes", + "MethodName": "CheckStorageInApprovedRegions", + "Rationale": "We need to create storage accounts in the same region as our customers due to some compliance requirements.", + "Recommendation": "Create a new storage account in the expected region [$($this.ControlSettings.Storage.RequiredRegion)] and use Azure copy tools to move the content over. Delete the old storage account after that.", + "Tags": [ + "SDL", + "TCP", + "Automated", + "StandardSku", + "PremiumSku", + "GeneralPurposeStorage", + "BlobStorage", + "HNSDisabled", + "ResourceLocked" + ], + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.ps1 b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.ps1 new file mode 100644 index 00000000..9144c961 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl/Storage.ext.ps1 @@ -0,0 +1,36 @@ +using namespace Microsoft.Azure.Management.Storage.Models +using namespace Microsoft.WindowsAzure.Storage.Shared.Protocol +Set-StrictMode -Version Latest +class StorageExt: Storage +{ + + StorageExt([string] $subscriptionId, [string] $resourceGroupName, [string] $resourceName): + Base($subscriptionId, $resourceGroupName, $resourceName) + { + } + + StorageExt([string] $subscriptionId, [SVTResource] $svtResource): + Base($subscriptionId, $svtResource) + { + } + + + hidden [ControlResult] CheckStorageInApprovedRegions([ControlResult] $controlResult) + { + $reqdRegion = $($this.ControlSettings.Storage.RequiredRegion) + $stgAcctName = $this.ResourceContext.ResourceName + + if($this.ResourceObject.Location -eq $reqdRegion) + { + + $controlResult.VerificationResult = [VerificationResult]::Passed + } + else + { + $controlResult.AddMessage("Note: Storage account [$stgAcctName] is not in the org-required region [$reqdRegion].") + $controlResult.VerificationResult = [VerificationResult]::Failed + } + + return $controlResult; + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Samples/SampleScript.ps1 b/07-Customizing-AzSK-for-your-Org/Samples/SampleScript.ps1 new file mode 100644 index 00000000..99d2f11d --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Samples/SampleScript.ps1 @@ -0,0 +1,180 @@ +# Variables used +#============================================================================================================== +$subId = ''#Enter the SubscriptionGuid id here +$oName = '' #Enter the name for your organization so that the policy name can use that +$depName = '' #Enter the name for your dept so that the policy name can use that +$policyFolder = "" # Enter the folder path where you want to keep org policy files +$policyDownloadFolder = $policyFolder+'_Dwn' +#============================================================================================================== + +#============================================================================================================== +# 1) Setting up org policy: Refer https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org#setting-up-org-policy for details +#============================================================================================================== +install-module AzSK -Scope CurrentUser -AllowClobber -Repository AzSKStaging -Force +import-Module $azSKModuleName +Write-Host "Import completed for [$azSKModuleName]!" +$azSKVer = (Get-Module $azSKModuleName).Version + +#============================================================================================================== +#-------------------------------------------------------------------------------------------------------------- +# 1a) If setting up new Org policy then follow the below steps: +#-------------------------------------------------------------------------------------------------------------- +<# Below command will create a basic policy structure in your local machine and create following resources in the subscription (if they don't already exist): + Resource Group: (AzSK---RG. + Storage Account: azsksa. + Application Insight: AzSK---AppInsight. + Monitoring dashboard (DevOpsKitMonitoring (DevOps Kit Monitoring Dashboard [Contoso-IT])) +#> + Install-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder +#-------------------------------------------------------------------------------------------------------------- +# 1b) To set your current session with the above policy so that you can subscription with that policy execute the iwr emitted in Install-AzSKOrganizationPolicy command +#-------------------------------------------------------------------------------------------------------------- +# 1c) Execute the below command to perform Subscription Scan with org policy +#-------------------------------------------------------------------------------------------------------------- + Get-AzSKSubscriptionSecurityStatus -SubscriptionId $SubId #You can verify the org name in the yellow line that says "Running with $oName$DeptName policy..." + + + +#============================================================================================================== +#2) Customizing Org-Policy: Refer https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org#modifying-and-customizing-org-policy +#============================================================================================================== +<# + Below are few examples to get familiarization with org-policy customization +# **Note**: 1) If you don't have existing configured Org policy, you can download policy to your local machine with below command. + 2) It is recommended to use the below command before making any changes to the policy (while trying the below examples) and updating the existing policy changes by Update-AzSKOrganizationPolicy command. + 3) If you are following step by step sample and want cummulative policy changes copy only the required settings from downloaded sample files wherever it is asked to copy content from downloaded files keeping the hierarchy of json files intact +#> + Get-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +#-------------------------------------------------------------------------------------------------------------- +#Example 1: Changing the default 'Running AzSK using…' message +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Open the AzSk.json from your local org-policy folder i.e. "$policyFolder\Config\AzSK.JSON" + Step 2: Edit the value for "Policy Message" say by adding field by adding 3 '*' characters on each side of your org name + Step 3: Save the file and to get these changes reflect in your online policy run the below Update-AzSKOrganizationPolicy command + Step 4: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +<# Testing: To check the updated message follow the below steps: + Step 1: Run "css" if you are working in the same powershell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + grs -s $subId -ResourceTypeName Storage -ControlIds 'Azure_Storage_AuthN_Dont_Allow_Anonymous'# You should see updated message ""Running AzSK...**$oName-$deptName **..." + +#-------------------------------------------------------------------------------------------------------------- +#Example 2: Changing a control setting for specific controls +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Copy the ControlSettings.json from the AzSK installation to your org-policy folder "$policyFolder\Config\ControlSettings.json" + Step 2: Remove everything except the "NoOfApprovedAdmins" line while keeping the JSON object hierarchy/structure intact + Step 3: Edit Number of Admins + Step 4: Save the file + Step 5: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) + Step 6: Run Update-AzSKOrganizationPolicy command as given below: +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +<# Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + gss -s $subId -ControlIds 'Azure_Subscription_AuthZ_Limit_Admin_Owner_Count' +<# Check detailed Logs to determine if control is passing or failing (see # of admins found) + Default threshold is '5' +#> +#-------------------------------------------------------------------------------------------------------------- +#Example 3: Creating a custom control 'baseline' for your org. Refer https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Readme.md#c-creating-a-custom-control-baseline-for-your-org +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Open the ControlSettings.json from your org-policy folder "$policyFolder\Config\ControlSettings.json" + Step 2: You can download sample ControlSettings.json from DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/EditBaseline/ControlSettings.json and copy its content to the ControlSettings.json file opened in Step1. You can use other controls of your choice. + Make sure the json format for defining Baseline controls is same as in the above referred sample. + Step 3: Save the edited file and run Update-AzSKOrganizationPolicy command as given below: + Step 4: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder +<# Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + gss -s $subId -ubc #The scan should now evaluate the controls added in Baseline + +#-------------------------------------------------------------------------------------------------------------- +#Example 4: Modify an existing SVT control json +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Copy the Storage.json from the AzSK installation("$HOME\Documents\WindowsPowerShell\Modules\$azskmoduleName\$azskVer\Framework\Configurations\SVT\SubscriptionCore.json") to your org-policy folder "$policyFolder\Config" + Step 2: Remove everything except the ControlId, the Id and the specific property to be modified. You can use sample from CustomizePolicy/EditSVTControl/SubscriptionCore.json where we have changed control description & severity + Step 3: Save the updated SubscriptionCore.json file. + Step 4: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) and then run Update-AzSKOrganizationPolicy command as given below: +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +<# Testing: + Step1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + gss -s $subId -ControlId Azure_Subscription_AuthZ_Limit_Admin_Owner_Count # The output csv should show updated description & Severity +#-------------------------------------------------------------------------------------------------------------- +#Example 5: Add Preview Baseline controls for your org +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Copy the content of sample files present in /AddPreviewBaseline/ControlSettings.json to your org-policy folder ControlSettings file (present at "$policyFolder\Config\ControlSettings.json") + We have added one automated control for AppService (TLS), one manual control for Storage (key-rotate) and one automated control for sub (PIM) + Step 2: Save the edited ControlSettings.json file and run Update-AzSKOrganizationPolicy command as given below: + Step 3: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) and then run Update-AzSKOrganizationPolicy command as given below: +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder +<#Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + gss -s $subId -UsePreviewBaselineControls # The controls added in the PreviewBaseline list for SubscriptionCore should be scanned + +#-------------------------------------------------------------------------------------------------------------- +#Example 6: Customizing Severity Labels for you org. Refer: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Readme.md#e-customizing-severity-labels +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Copy the content of sample files present in DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/EditSeverityLabel/ControlSettings.json to your org-policy folder ControlSettings file ("$policyFolder\Config\ControlSettings.json") + Step 2: Save the edited ControlSettings.json file and run Update-AzSKOrganizationPolicy command as given below: + Step 3: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) and then run Update-AzSKOrganizationPolicy command as given below: +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder +<#Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + gss -s $subId -Severity 'FixItNow' #if you have used some other values you can supply them in comma separated format to Severity parameter. +# The above should scan critical control which would now have 'FixItNow' severity. You can check the severity column in output SecurityReport.csv + +#-------------------------------------------------------------------------------------------------------------- +#============================================================================================================== +#3) Extending AzSK SVT +#-------------------------------------------------------------------------------------------------------------- +# 3a) Extend existing control or Modify existing logic. Refer https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module#b-extending-a-gss-svt +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Download the sample Storage.ext.ps1 file from DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/ and save it to your local policy folder "$policyFolder\Config" + Step 2: Download the sample Storage.ext.json file from DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/ExtendingExistingGRSControl/ and save it to your local policy folder "$policyFolder\Config" + Step 3: Ensure the ControlSettings.json has ExemptedHttpsRegions setting, if it is not present you can get copy the setting from ExtendingAzSKModule/Sample/ExtendingExistingGRSControl/ControlSettings.json and paste them in + your local policy ControlSettings.json file + Step 4: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) and then run Update-AzSKOrganizationPolicy command as given below: + +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +<# Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + grs -s $subId -ResourceTypeName Storage -ControlIds 'Azure_Storage_DP_Encrypt_In_Transit'# The scan should pass the storage account which don’t have HTTPS enabled but present in exempted region + +#-------------------------------------------------------------------------------------------------------------- +# 3b) New control for a resource. Refer https://github.com/azsk/DevOpsKit-docs/tree/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module#b-extending-a-grs-svt +#-------------------------------------------------------------------------------------------------------------- +<# Step 1: Download the sample Storage.ext.ps1 file from DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl and save it to your local policy folder "$policyFolder\Config" + Step 2: Download the sample Storage.ext.json file from DevOpsKit-docs/07-Customizing-AzSK-for-your-Org/Samples/NewGRSControl and save it to your local policy folder "$policyFolder\Config" + Step 3: Ensure the ControlSettings.json has ExemptedHttpsRegions setting, if it is not present you can get copy the setting from ExtendingAzSKModule/Sample/ExtendingExistingGRSControl/ControlSettings.json and paste them in + your local policy ControlSettings.json file + Step 4: Edit the ServerConfigMetadata.json file in the org-policy folder and create an entry for this file (if not already there) and then run Update-AzSKOrganizationPolicy command as given below: + +#> + Update-AzSKOrganizationPolicy -SubscriptionId $subId -OrgName $oName -DepartmentName $depName -PolicyFolderPath $policyFolder + +<#Testing: + Step 1: Run "css" if you are working in the same PowerShell session but ff you have started a fresh one, run import-module AzSK and then run scan using below command +#> + grs -s $subId -ResourceTypeName Storage -ControlIds 'Azure_Storage_Create_In_Approved_Regions' # The scan should pass the storage account that are in 'eastus2' region + grs -s $subId -ResourceTypeName Storage -ControlIds 'Azure_Storage_Create_In_Approved_Regions' -rgns 'AzSKRG'# The scan should pass the storage account in AzSK + +#-------------------------------------------------------------------------------------------------------------- + +#============================================================================================================== diff --git a/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.ps1.txt b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.ps1.txt new file mode 100644 index 00000000..504a97f3 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.ps1.txt @@ -0,0 +1,683 @@ +Param( + +[string] +[Parameter(Mandatory = $true)] + $SubscriptionId, + +[string] +[Parameter(Mandatory = $true)] +$PolicyResourceGroupName, + +[string] +$PolicyCopyFolderPath = $env:TEMP + "\" + $ModuleName + "\Policies\", + +[string] +$PolicyBackupFolderPath = $env:TEMP + "\" + $ModuleName + "\Backup\Policies\", + +[switch] +$RestoreFromBackup +) + +#Constants +$ModuleName = "AzSK" +$BlankSubId = "00000000-0000-0000-0000-000000000000" +$RepoName = "PSGallery" + + +#Login and Set context to policy subscription +function Login +{ + $currentContext = Get-AzContext + if((-not $currentContext) -or ($currentContext -and ((-not $currentContext.Subscription -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) ` + -or -not $currentContext.Account))) + { + WriteMessage "No active Azure login session found. Initiating login flow..." + + if($this.SubscriptionContext.SubscriptionId -ne $BlankSubId) + { + $rmLogin = Connect-AzAccount -SubscriptionId $SubscriptionId + } + else + { + $rmLogin = Connect-AzAccount + } + + if($rmLogin) + { + $currentContext = $rmLogin.Context; + } + } + + if($currentContext -and $currentContext.Subscription -and $currentContext.Subscription.Id) + { + if(($currentContext.Subscription.Id -ne $SubscriptionId) -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) + { + $currentContext = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop + + + # $currentContext will contain the desired subscription (or $null if id is wrong or no permission) + if ($null -eq $currentContext) + { + throw [SuppressedException] ("Invalid Subscription Id [" + $this.SubscriptionContext.SubscriptionId + "]") + } + } + } +} +#Login End + +#Function to get substring from regular expression +function GetSubString($CotentString, $Pattern ) +{ + $result = [regex]::match($CotentString, $pattern) + if(($result | Measure-Object).Count -gt 0) + { + return $result.Groups[1].Value + } + else + { + return [string]::Empty + } + + +} + + + +#Validate if string is empty and return default string +function IsStringEmpty($String) +{ + if([string]::IsNullOrEmpty($String)) + { + return "Not Available" + } + else + { + return $String + } +} + +#Message types +enum MessageType +{ + Error + Warning + Info + Update + Default +} + +#Function to print messages on console +function WriteMessage([string] $message,[string] $messageType) +{ + if(-not $message) + { + return; + } + + $colorCode = [System.ConsoleColor]::White + + switch($messageType) + { + ([MessageType]::Error) { + $colorCode = [System.ConsoleColor]::Red + } + ([MessageType]::Warning) { + $colorCode = [System.ConsoleColor]::Yellow + } + ([MessageType]::Info) { + $colorCode = [System.ConsoleColor]::Cyan + } + ([MessageType]::Update) { + $colorCode = [System.ConsoleColor]::Green + } + ([MessageType]::Default) { + $colorCode = [System.ConsoleColor]::White + } + } + Write-Host $message -ForegroundColor $colorCode +} + +function AddPropertyIfNotExists($jsonObject,$propertyName,$propertyValue) +{ + + if(-not $jsonObject.$($propertyName)) + { + WriteMessage "Adding property: [$propertyName]" $([MessageType]::Info) + $jsonObject | Add-Member -MemberType NoteProperty -Name $propertyName -Value $propertyValue -PassThru + return $true + } + elseif( $jsonObject.$($propertyName) -notlike "*$propertyValue*") + { + WriteMessage "Property Name: [$propertyName]" $([MessageType]::Info) + $jsonObject.$($propertyName) = $propertyValue + return $true + } + else + { + return $false + } +} + +function SetUtf8Encoding([System.IO.FileInfo] $file) +{ + if($file) + { + $fileContent = Get-Content -Path $file.FullName; + if($fileContent) + { + Out-File -InputObject $fileContent -Force -FilePath $file.FullName -Encoding utf8 + } + } +} + +#BOM replace function +function RemoveUtf8BOM([System.IO.FileInfo] $file) +{ + SetUtf8Encoding $file + if($file) + { + $byteBuffer = New-Object System.Byte[] 3 + $reader = $file.OpenRead() + $bytesRead = $reader.Read($byteBuffer, 0, 3); + if ($bytesRead -eq 3 -and + $byteBuffer[0] -eq 239 -and + $byteBuffer[1] -eq 187 -and + $byteBuffer[2] -eq 191) + { + $tempFile = [System.IO.Path]::GetTempFileName() + $writer = [System.IO.File]::OpenWrite($tempFile) + $reader.CopyTo($writer) + $writer.Dispose() + $reader.Dispose() + Move-Item -Path $tempFile -Destination $file.FullName -Force + } + else + { + $reader.Dispose() + } + } +} + + +#Function to upload blob to policy store +function UploadFilesToBlob([PSObject] $storageContext, [string] $containerName, [string] $blobPath, [System.IO.FileInfo[]] $filesToUpload, [bool] $overwrite) +{ + $result = $null; + + if($filesToUpload -and $filesToUpload.Count -ne 0) + { + WriteMessage ("Uploading [$($filesToUpload.Count)] file(s) to container [$containerName]...") $([MessageType]::Info) + $filesToUpload | + ForEach-Object { + $blobName = $_.Name; + if(-not [string]::IsNullOrWhiteSpace($blobPath)) + { + $blobName = $blobPath + "/" + $blobName; + } + + RemoveUtf8BOM $_ + $loopValue = 3 + $sleepValue =10 + while($loopValue -gt 0) + { + $loopValue = $loopValue - 1; + try { + if($overwrite) + { + Set-AzStorageBlobContent -Blob $blobName -Container $containerName -File $_.FullName -Context $storageContext -Force | Out-Null + } + else + { + $currentBlob = Get-AzStorageBlob -Blob $blobName -Container $containerName -Context $storageContext -ErrorAction Ignore + + if(-not $currentBlob) + { + Set-AzStorageBlobContent -Blob $blobName -Container $containerName -File $_.FullName -Context $storageContext | Out-Null + } + } + $loopValue = 0; + } + catch { + #sleep for incremental 10 seconds before next retry; + Start-Sleep -Seconds $sleepValue; + $sleepValue = $sleepValue + 10; + } + } + + } + WriteMessage ("All files have been uploaded to container [$containerName]") $([MessageType]::Info) + } +} + + + +#***************************************** Execution started ******************************************** +WriteMessage "================================================================================" $([MessageType]::Info) +WriteMessage "Updating your AzSK Org Policy setup..." $([MessageType]::Info) +WriteMessage "================================================================================" $([MessageType]::Info) +Login + +if(-not $RestoreFromBackup) +{ + try + { + #a. Validate presense of policy resource group + $policyResourceGroup= Get-AzResourceGroup -Name $PolicyResourceGroupName -ErrorAction SilentlyContinue + if(-not $policyResourceGroup) + { + WriteMessage "`Policy resource group not found" $([MessageType]::Error) + return + } + else + { + + WriteMessage "Found resource group: [$($policyResourceGroup.ResourceGroupName)]" $([MessageType]::Info) + } + + #b. Validate presense of policy resources storage, app insight and monitoring dashboard + $policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName + #Check if poliy store is present + $policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if(($policyStore | Measure-Object).Count -eq 0) + { + WriteMessage "Policy storage account not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + else + { + WriteMessage "Found storage account: [$($policyStore.Name)]" $([MessageType]::Info) + } + + #Check if app insight is present + $appInsight = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Insights/components" } + if(($appInsight | Measure-Object).Count -eq 0) + { + WriteMessage "Policy app insight not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + else + { + WriteMessage "Found storage account: [$($policyStore.Name)]" $([MessageType]::Info) + } + + #Check if monitoring dashboard is present + $monitoringDashboard = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Portal/dashboards" } + if(($monitoringDashboard | Measure-Object).Count -eq 0) + { + WriteMessage "Warning: Monitoring dashboard is missing on Org policy. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Warning) + } + else + { + WriteMessage "Found monitoring dashboard: [$($monitoringDashboard.Name)]" $([MessageType]::Info) + } + + + #region Check 02: Download policies into local + + WriteMessage "Copying policies to local machine..." $([MessageType]::Info) + $PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name + $currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https + $containerList = Get-AzStorageContainer -Context $currentContext + $PolicyContainerName = "policies" + $sasToken = New-AzStorageContainerSASToken -Name $PolicyContainerName -Context $currentContext -ExpiryTime (Get-Date).AddMonths(6) -Permission rl -Protocol HttpsOnly -StartTime (Get-Date).AddDays(-1) + + if(-not (Test-Path "$PolicyCopyFolderPath")) + { + mkdir -Path "$PolicyCopyFolderPath" -ErrorAction Stop | Out-Null + } + else + { + Remove-Item -Path "$PolicyCopyFolderPath\*" -Force -Recurse + } + + $policyBlobslist = @() + $containerList | ForEach-Object { + $PolicyContainerName = $_.Name + $PolicyBlobs = Get-AzStorageBlob -Container $PolicyContainerName -Context $currentContext + + $PolicyContainerPath = "$PolicyCopyFolderPath\$PolicyContainerName" + if(-not (Test-Path $PolicyContainerPath)) + { + mkdir -Path $PolicyContainerPath -ErrorAction Stop | Out-Null + } + else + { + Remove-Item -Path "$PolicyContainerPath\*" -Force -Recurse + } + + foreach ($blob in $PolicyBlobs) + { + $policyBlobslist +=$blob + Get-AzStorageBlobContent ` + -Container $PolicyContainerName -Blob $blob.Name ` + -Context $currentContext -Destination "$PolicyContainerPath" -Force | Out-Null + } + } + + + #Create backup before modification + if(-not (Test-Path "$PolicyBackupFolderPath")) + { + mkdir -Path "$PolicyBackupFolderPath" -ErrorAction Stop | Out-Null + } + else + { + $backupContent= Get-ChildItem -Path $PolicyBackupFolderPath + if(($backupContent | Measure-Object).Count -gt 0) + { + WriteMessage "Warning: Backup folder already contains some files.This can override existing backup files present in folder : [$PolicyBackupFolderPath].`nDo you want to continue(Y/N):" $([MessageType]::Warning) + $answer= Read-Host + if($answer.ToLower() -eq "y" ) + { + Remove-Item -Path "$PolicyBackupFolderPath\*" -Force -Recurse + } + else + { + return + } + } + } + + Copy-Item -Path $PolicyCopyFolderPath -Destination "$PolicyBackupFolderPath" -Recurse -Force + WriteMessage "Completed copying policies to local machine..." $([MessageType]::Update) + #endregion + + #region Check 04: Validate AzSKPre + $AzSKPre = $policyBlobslist | Where-Object {$_.Name -like "*AzSK.Pre.json*"} + #Validate CurrentVersionForOrg + $LatestAzSKVersion = Find-Module $ModuleName -Repository $RepoName + $AzSKVersion = Get-Module $ModuleName -ListAvailable | Select -First 1 + if(($AzSKPre | Measure-Object).Count -eq 0) + { + WriteMessage "AzSKPre config not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + $AzSKPreConfigPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "AzSK.Pre.json" -Recurse + $AzSKPreConfigContent = Get-Content -Path $AzSKPreConfigPath.FullName | ConvertFrom-Json + if($AzSKPreConfigContent.CurrentVersionForOrg -ne $LatestAzSKVersion.Version.ToString()) + { + WriteMessage "Warning: Your Org policy is configured with older AzSK version[$($AzSKPreConfigContent.CurrentVersionForOrg)]. Consider updating it to latest stable available version [$($LatestAzSKVersion.Version.Tostring())]" $([MessageType]::Warning) + } + } + #endregion + + + #region Check 03: Validate installer file + $Installer = Get-ChildItem -Path $PolicyCopyFolderPath -Include "$($ModuleName)-EasyInstaller.ps1" -Recurse + if(($Installer | Measure-Object).Count -eq 0) + { + WriteMessage "Installer not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating installer file..." $([MessageType]::Info) + $InstallerContent = Get-Content -Path $($Installer.FullName) + $AzSKConfig = $policyBlobslist | Where-Object {$_.Name -like "*AzSK.json*"} + + #Validate OnlinePolicyStoreUrl + $pattern = 'OnlinePolicyStoreUrl = "(.*?)"' + $InstallerPolicyUrl = GetSubString $InstallerContent $pattern + + $policyContainerUrl= $AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + "/```$(```$Version)/```$(```$FileName)" + if($policyContainerUrl -and $InstallerPolicyUrl -notlike "*$policyContainerUrl*" ) + { + WriteMessage "Property Name: [OnlinePolicyStoreUrl]" $([MessageType]::Info) + $InstallerContent=$InstallerContent.Replace($InstallerPolicyUrl,($AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + "/```$(```$Version)/```$(```$FileName)" + $sasToken )) + } + + #Validate AutoUpdateCommand command + $pattern = 'AutoUpdateCommand = "(.*?)"' + $autoUpdateCommandUrl = GetSubString $InstallerContent $pattern + $Installerblob = $policyBlobslist | Where-Object {$_.Name -like "*AzSK-EasyInstaller.ps1*"} + $installerUrl = $Installerblob.ICloudBlob.Uri.AbsoluteUri + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex" + if($autoUpdateCommandUrl -notlike "*$installerUrl*" ) + { + WriteMessage "Property Name: [AutoUpdateCommand]" $([MessageType]::Info) + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex"; + $InstallerContent=$InstallerContent.Replace($InstallerPolicyUrl,$IWRCommand) + } + + + #Validate AzSKConfigURL + $pattern = 'AzSKConfigURL = "(.*?)"' + $InstallerAzSKPreUrl = GetSubString $InstallerContent $pattern + + $AzSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + if($InstallerAzSKPreUrl -notlike "*$AzSKPreUrl*") + { + WriteMessage "Property Name: [AzSKConfigURL]" $([MessageType]::Info) + $AzSKPreUrl = $AzSKPreUrl + $sasToken + $InstallerContent=$InstallerContent.Replace($InstallerAzSKPreUrl,$AzSKPreUrl) + } + + Out-File -InputObject $InstallerContent -Force -FilePath $($Installer.FullName) -Encoding utf8 + WriteMessage "Completed updating installer file..." $([MessageType]::Update) + } + #endregion + + #region Check 05: Validate CoreSetup + $RunbookCoreSetupPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "RunbookCoreSetup.ps1" -Recurse + $RunbookCoreSetup = $policyBlobslist | Where-Object {$_.Name -like "*RunbookCoreSetup.ps1*"} + if(($RunbookCoreSetupPath | Measure-Object).Count -eq 0) + { + WriteMessage "RunbookCoreSetup not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating runbookCoreSetup file..." $([MessageType]::Info) + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath.FullName + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + $AzSkVersionForOrgUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if([string]::IsNullOrEmpty($coreSetupAzSkVersionForOrgUrl) ) + { + WriteMessage "Warning:Org policy contains older version of RunbookCoreSetup.ps1 and RunbookScanAgent.ps1.`nWould you like to update it with latest version:" $([MessageType]::Warning) + $answer= Read-Host + if($answer.ToLower() -eq "y" ) + { + #Take latest + WriteMessage "Copying latest version of 'RunbookCoreSetup.ps1'..." $([MessageType]::Info) + $RunbookUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookCoreSetup.ps1" + + IWR -Uri $RunbookUrl -OutFile $($RunbookCoreSetupPath.FullName) + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath.FullName + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + WriteMessage "Copying latest version of 'RunbookScanAgent.ps1'..." $([MessageType]::Info) + $RunbookUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookScanAgent.ps1" + $RunbookScanAgentPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "RunbookScanAgent.ps1" -Recurse + IWR -Uri $RunbookUrl -OutFile $($RunbookScanAgentPath.FullName) + + } + else + { + WriteMessage "Skipping RunbookCoreSetup and RunbookScanAgent updates." $([MessageType]::Info) + } + } + if($coreSetupAzSkVersionForOrgUrl -ne "Not Available" -and $coreSetupAzSkVersionForOrgUrl -notlike "*$AzSkVersionForOrgUrl*" ) + { + $AzSkVersionForOrgUrl += $sasToken + WriteMessage "Property Name: [AzSKVersionForOrg]" $([MessageType]::Info) + $RunbookCoreSetupContent = $RunbookCoreSetupContent.Replace($coreSetupAzSkVersionForOrgUrl,$AzSkVersionForOrgUrl) + } + Out-File -InputObject $RunbookCoreSetupContent -Force -FilePath $($RunbookCoreSetupPath.FullName) -Encoding utf8 + WriteMessage "Completed updating runbookCoreSetup file..." $([MessageType]::Update) + } + #endregion + + #region Check 06: Validate AzSKConfig + $AzSKConfigPath = Get-ChildItem -Path $PolicyCopyFolderPath -Include "AzSK.json" -Recurse + if(($AzSKConfigPath | Measure-Object).Count -eq 0) + { + WriteMessage "AzSK config not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating AzSKConfig file..." $([MessageType]::Info) + $AzSKConfigContent = Get-Content -Path $AzSKConfigPath.FullName | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $RunbookCoreSetupUrl = $RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri + + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'CASetupRunbookURL' $RunbookCoreSetupUrl + if($IsPropertyModified) + { + $AzSKConfigContent.CASetupRunbookURL = $RunbookCoreSetupUrl + $sasToken + WriteMessage "Warning: CASetupRunbookURL is updated with latest Org policy CA setup url.`nYou need to run Update-AzSKContinuousAssurance on installed CA's.`nFor more details refer FAQ at: https://aka.ms/devopskit/orgpolicy/healthcheck" $([MessageType]::Warning) + } + + #Validate ControlTelemetryKey + $appInsightResource= Get-AzApplicationInsights -ResourceGroupName $appInsight.ResourceGroupName -Name $appInsight.Name + $InstrumentationKey = $appInsightResource.InstrumentationKey + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'ControlTelemetryKey' $InstrumentationKey + + $azSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'AzSKConfigURL' $azSKPreUrl + if($IsPropertyModified) + { + $AzSKConfigContent.AzSKConfigURL = $azSKPreUrl + $sasToken + } + + #Validate PolicyOrgName + if(-not $AzSKConfigContent.PolicyOrgName -and [string]::IsNullOrEmpty($AzSKConfigContent.PolicyOrgName) ) + { + if(-not [string]::IsNullOrEmpty($AzSKConfigContent.PolicyMessage)) + { + $pattern = 'using (.*?) policy' + $OrgName = GetSubString $($AzSKConfigContent.PolicyMessage) $pattern + if(-not [string]::IsNullOrEmpty($OrgName)) + { + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'PolicyOrgName' $OrgName + } + } + + } + + #Validate Installation command + $Installerblob = $policyBlobslist | Where-Object {$_.Name -like "*AzSK-EasyInstaller.ps1*"} + $installerUrl = $Installerblob.ICloudBlob.Uri.AbsoluteUri + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex"; + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'InstallationCommand' $IWRCommand + + + $AzSKConfigContent | ConvertTo-Json -Depth 10 | Out-File -Force -FilePath $($AzSKConfigPath.FullName) -Encoding utf8 + WriteMessage "Completed updating AzSKConfig file..." $([MessageType]::Update) + } + #region Upload updated configurations to policy store + WriteMessage "Uploading updated configurations to policy store..." $([MessageType]::Info) + Get-ChildItem -Path $PolicyCopyFolderPath | ForEach-Object { + $ContainerName= $_.Name + $directoryList = Get-ChildItem -Path $_.FullName -Recurse -Directory + if(($directoryList | Measure-Object).Count -gt 0) + { + Get-ChildItem -Path $_.FullName -Recurse -Directory | ForEach-Object { + $blobPath= $_.Name + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + } + else + { + $blobPath = [string]::Empty + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + + } + + #endregion + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Policy updated successfully." $([MessageType]::Update) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Updated policy folder path: $PolicyCopyFolderPath" $([MessageType]::Info) + WriteMessage "Backup policy folder path: $PolicyBackupFolderPath" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "`nNow policy has been updated with latest configurations. You can perform below steps to smoke test policy configurations" $([MessageType]::Info) + WriteMessage "`t 1. Run installer(IWR) and validate if it is able to install AzSK successfully." $([MessageType]::Info) + WriteMessage "`t`t $IWRCommand" $([MessageType]::Update) + WriteMessage "`t 2. Run scan command in local machine and validate there is no exceptions" $([MessageType]::Info) + WriteMessage "`t`t Get-AzSKSubscriptionSecurityStatus -SubscriptionId $SubscriptionId" $([MessageType]::Update) + WriteMessage "`t 3. Trigger CA runbook and check if job gets executed and scans are logged in storage account [$($policyStore.Name)]" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "`n`t If one of the above step is failing, you can restore policy settings with the help of backup using same script with parameter RestoreFromBackup)." $([MessageType]::Info) + WriteMessage "`t If all steps are passing, you can copy these latest updated policy configurations to your Org policy folder which was created at time of policy installation and used to updated policy " $([MessageType]::Info) + WriteMessage "`t Source Path : [$PolicyCopyFolderPath] Destination(Default) Path : [/AzSK-[OrgName]-Policy/]" $([MessageType]::Info) + WriteMessage "`t [policies\3.1803.0] ----> [Config]" $([MessageType]::Info) + WriteMessage "`t [policies\1.0.0] ----> [CA-Runbook]" $([MessageType]::Info) + WriteMessage "`t [installer] ----> [Installer]" $([MessageType]::Info) + WriteMessage "================================================================================" + } + catch + { + WriteMessage "Exception occured during policy update... $($_.Tostring())" $([MessageType]::Error) + } + + #endregion + +} +else +{ + if( Test-Path $PolicyBackupFolderPath) + { + $backupContent= Get-ChildItem -Path $PolicyBackupFolderPath + if(($backupContent | Measure-Object).Count -eq 0) + { + WriteMessage "Backup folder does not contains any files." $([MessageType]::Error) + return + } + else + { + WriteMessage "Uploading configurations from backup folder to policy store..." $([MessageType]::Info) + $policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName + #Check if poliy store is present + $policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if(($policyStore | Measure-Object).Count -eq 0) + { + WriteMessage "Policy storage account not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + $PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name + $currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https + Get-ChildItem -Path $PolicyBackupFolderPath| ForEach-Object { + $ContainerName= $_.Name + $directoryList = Get-ChildItem -Path $_.FullName -Recurse -Directory + if(($directoryList | Measure-Object).Count -gt 0) + { + Get-ChildItem -Path $_.FullName -Recurse -Directory | ForEach-Object { + $blobPath= $_.Name + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + } + else + { + $blobPath = [string]::Empty + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + + } + + #endregion + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Policy updated successfully." $([MessageType]::Update) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Please perform below tasks to validate successful update of policy from backup folder" $([MessageType]::Info) + WriteMessage "`t 1. Run installer(IWR) and validate if it is able to install AzSK successfully" $([MessageType]::Info) + WriteMessage "`t 2. Run scan command in local machine with Org policy and validate there is no exceptions" $([MessageType]::Info) + WriteMessage "`t 3. Run CA runbook and check if job gets executed and scan results are logged in storage account" $([MessageType]::Info) + WriteMessage "`t 4. If any of above steps is failing after policy update from backup. You can contact support team to resolve the issue" $([MessageType]::Info) + WriteMessage "================================================================================" $([MessageType]::Info) + } + + } + else + { + WriteMessage "Backup folder does not exists" $([MessageType]::Warning) + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.txt b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.txt new file mode 100644 index 00000000..4e0b137e --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.txt @@ -0,0 +1,685 @@ +Param( + +[string] +[Parameter(Mandatory = $true)] + $SubscriptionId, + +[string] +[Parameter(Mandatory = $true)] +$PolicyResourceGroupName, + +[string] +$PolicyCopyFolderPath = $env:TEMP + "\" + $ModuleName + "\Policies\", + +[string] +$PolicyBackupFolderPath = $env:TEMP + "\" + $ModuleName + "\Backup\Policies\", + +[switch] +$RestoreFromBackup +) + +#Constants +$ModuleName = "AzSK" +$BlankSubId = "00000000-0000-0000-0000-000000000000" +$RepoName = "PSGallery" + + +#Login and Set context to policy subscription +function Login +{ + $currentContext = Get-AzContext + if((-not $currentContext) -or ($currentContext -and ((-not $currentContext.Subscription -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) ` + -or -not $currentContext.Account))) + { + WriteMessage "No active Azure login session found. Initiating login flow..." + + if($this.SubscriptionContext.SubscriptionId -ne $BlankSubId) + { + $rmLogin = Connect-AzAccount -SubscriptionId $SubscriptionId + } + else + { + $rmLogin = Connect-AzAccount + } + + if($rmLogin) + { + $currentContext = $rmLogin.Context; + } + } + + if($currentContext -and $currentContext.Subscription -and $currentContext.Subscription.Id) + { + if(($currentContext.Subscription.Id -ne $SubscriptionId) -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) + { + $currentContext = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop + + + # $currentContext will contain the desired subscription (or $null if id is wrong or no permission) + if ($null -eq $currentContext) + { + throw [SuppressedException] ("Invalid Subscription Id [" + $this.SubscriptionContext.SubscriptionId + "]") + } + } + } +} +#Login End + +#Function to get substring from regular expression +function GetSubString($CotentString, $Pattern ) +{ + $result = [regex]::match($CotentString, $pattern) + if(($result | Measure-Object).Count -gt 0) + { + return $result.Groups[1].Value + } + else + { + return [string]::Empty + } + + +} + + + +#Validate if string is empty and return default string +function IsStringEmpty($String) +{ + if([string]::IsNullOrEmpty($String)) + { + return "Not Available" + } + else + { + return $String + } +} + +#Message types +enum MessageType +{ + Error + Warning + Info + Update + Default +} + +#Function to print messages on console +function WriteMessage([string] $message,[string] $messageType) +{ + if(-not $message) + { + return; + } + + $colorCode = [System.ConsoleColor]::White + + switch($messageType) + { + ([MessageType]::Error) { + $colorCode = [System.ConsoleColor]::Red + } + ([MessageType]::Warning) { + $colorCode = [System.ConsoleColor]::Yellow + } + ([MessageType]::Info) { + $colorCode = [System.ConsoleColor]::Cyan + } + ([MessageType]::Update) { + $colorCode = [System.ConsoleColor]::Green + } + ([MessageType]::Default) { + $colorCode = [System.ConsoleColor]::White + } + } + Write-Host $message -ForegroundColor $colorCode +} + +function AddPropertyIfNotExists($jsonObject,$propertyName,$propertyValue) +{ + + if(-not $jsonObject.$($propertyName)) + { + WriteMessage "Adding property: [$propertyName]" $([MessageType]::Info) + $jsonObject | Add-Member -MemberType NoteProperty -Name $propertyName -Value $propertyValue -PassThru + return $true + } + elseif( $jsonObject.$($propertyName) -notlike "*$propertyValue*") + { + WriteMessage "Property Name: [$propertyName]" $([MessageType]::Info) + $jsonObject.$($propertyName) = $propertyValue + return $true + } + else + { + return $false + } +} + +function SetUtf8Encoding([System.IO.FileInfo] $file) +{ + if($file) + { + $fileContent = Get-Content -Path $file.FullName; + if($fileContent) + { + Out-File -InputObject $fileContent -Force -FilePath $file.FullName -Encoding utf8 + } + } +} + +#BOM replace function +function RemoveUtf8BOM([System.IO.FileInfo] $file) +{ + SetUtf8Encoding $file + if($file) + { + $byteBuffer = New-Object System.Byte[] 3 + $reader = $file.OpenRead() + $bytesRead = $reader.Read($byteBuffer, 0, 3); + if ($bytesRead -eq 3 -and + $byteBuffer[0] -eq 239 -and + $byteBuffer[1] -eq 187 -and + $byteBuffer[2] -eq 191) + { + $tempFile = [System.IO.Path]::GetTempFileName() + $writer = [System.IO.File]::OpenWrite($tempFile) + $reader.CopyTo($writer) + $writer.Dispose() + $reader.Dispose() + Move-Item -Path $tempFile -Destination $file.FullName -Force + } + else + { + $reader.Dispose() + } + } +} + + +#Function to upload blob to policy store +function UploadFilesToBlob([PSObject] $storageContext, [string] $containerName, [string] $blobPath, [System.IO.FileInfo[]] $filesToUpload, [bool] $overwrite) +{ + $result = $null; + + if($filesToUpload -and $filesToUpload.Count -ne 0) + { + WriteMessage ("Uploading [$($filesToUpload.Count)] file(s) to container [$containerName]...") $([MessageType]::Info) + $filesToUpload | + ForEach-Object { + $blobName = $_.Name; + if(-not [string]::IsNullOrWhiteSpace($blobPath)) + { + $blobName = $blobPath + "/" + $blobName; + } + + RemoveUtf8BOM $_ + $loopValue = 3 + $sleepValue =10 + while($loopValue -gt 0) + { + $loopValue = $loopValue - 1; + try { + if($overwrite) + { + Set-AzStorageBlobContent -Blob $blobName -Container $containerName -File $_.FullName -Context $storageContext -Force | Out-Null + } + else + { + $currentBlob = Get-AzStorageBlob -Blob $blobName -Container $containerName -Context $storageContext -ErrorAction Ignore + + if(-not $currentBlob) + { + Set-AzStorageBlobContent -Blob $blobName -Container $containerName -File $_.FullName -Context $storageContext | Out-Null + } + } + $loopValue = 0; + } + catch { + #sleep for incremental 10 seconds before next retry; + Start-Sleep -Seconds $sleepValue; + $sleepValue = $sleepValue + 10; + } + } + + } + WriteMessage ("All files have been uploaded to container [$containerName]") $([MessageType]::Info) + } +} + + + +#***************************************** Execution started ******************************************** +WriteMessage "================================================================================" $([MessageType]::Info) +WriteMessage "Updating your AzSK Org Policy setup..." $([MessageType]::Info) +WriteMessage "================================================================================" $([MessageType]::Info) +Login + +if(-not $RestoreFromBackup) +{ + try + { + #a. Validate presense of policy resource group + $policyResourceGroup= Get-AzResourceGroup -Name $PolicyResourceGroupName -ErrorAction SilentlyContinue + if(-not $policyResourceGroup) + { + WriteMessage "`Policy resource group not found" $([MessageType]::Error) + return + } + else + { + + WriteMessage "Found resource group: [$($policyResourceGroup.ResourceGroupName)]" $([MessageType]::Info) + } + + #b. Validate presense of policy resources storage, app insight and monitoring dashboard + $policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName + #Check if poliy store is present + $policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if(($policyStore | Measure-Object).Count -eq 0) + { + WriteMessage "Policy storage account not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + else + { + WriteMessage "Found storage account: [$($policyStore.Name)]" $([MessageType]::Info) + } + + #Check if app insight is present + $appInsight = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Insights/components" } + if(($appInsight | Measure-Object).Count -eq 0) + { + WriteMessage "Policy app insight not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + else + { + WriteMessage "Found storage account: [$($policyStore.Name)]" $([MessageType]::Info) + } + + #Check if monitoring dashboard is present + $monitoringDashboard = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Portal/dashboards" } + if(($monitoringDashboard | Measure-Object).Count -eq 0) + { + WriteMessage "Warning: Monitoring dashboard is missing on Org policy. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Warning) + } + else + { + WriteMessage "Found monitoring dashboard: [$($monitoringDashboard.Name)]" $([MessageType]::Info) + } + + + #region Check 02: Download policies into local + + WriteMessage "Copying policies to local machine..." $([MessageType]::Info) + $PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name + $currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https + $containerList = Get-AzStorageContainer -Context $currentContext + $PolicyContainerName = "policies" + $sasToken = New-AzStorageContainerSASToken -Name $PolicyContainerName -Context $currentContext -ExpiryTime (Get-Date).AddMonths(6) -Permission rl -Protocol HttpsOnly -StartTime (Get-Date).AddDays(-1) + + if(-not (Test-Path "$PolicyCopyFolderPath")) + { + mkdir -Path "$PolicyCopyFolderPath" -ErrorAction Stop | Out-Null + } + else + { + Remove-Item -Path "$PolicyCopyFolderPath\*" -Force -Recurse + } + + $policyBlobslist = @() + $containerList | ForEach-Object { + $PolicyContainerName = $_.Name + $PolicyBlobs = Get-AzStorageBlob -Container $PolicyContainerName -Context $currentContext + + $PolicyContainerPath = "$PolicyCopyFolderPath\$PolicyContainerName" + if(-not (Test-Path $PolicyContainerPath)) + { + mkdir -Path $PolicyContainerPath -ErrorAction Stop | Out-Null + } + else + { + Remove-Item -Path "$PolicyContainerPath\*" -Force -Recurse + } + + foreach ($blob in $PolicyBlobs) + { + $policyBlobslist +=$blob + Get-AzStorageBlobContent ` + -Container $PolicyContainerName -Blob $blob.Name ` + -Context $currentContext -Destination "$PolicyContainerPath" -Force | Out-Null + } + } + + + #Create backup before modification + if(-not (Test-Path "$PolicyBackupFolderPath")) + { + mkdir -Path "$PolicyBackupFolderPath" -ErrorAction Stop | Out-Null + } + else + { + $backupContent= Get-ChildItem -Path $PolicyBackupFolderPath + if(($backupContent | Measure-Object).Count -gt 0) + { + WriteMessage "Warning: Backup folder already contains some files.This can override existing backup files present in folder : [$PolicyBackupFolderPath].`nDo you want to continue(Y/N):" $([MessageType]::Warning) + $answer= Read-Host + if($answer.ToLower() -eq "y" ) + { + Remove-Item -Path "$PolicyBackupFolderPath\*" -Force -Recurse + } + else + { + return + } + } + } + + Copy-Item -Path $PolicyCopyFolderPath -Destination "$PolicyBackupFolderPath" -Recurse -Force + WriteMessage "Completed copying policies to local machine..." $([MessageType]::Update) + #endregion + + #region Check 04: Validate AzSKPre + $AzSKPre = $policyBlobslist | Where-Object {$_.Name -like "*AzSK.Pre.json*"} + #Validate CurrentVersionForOrg + $LatestAzSKVersion = Find-Module $ModuleName -Repository $RepoName + $AzSKVersion = Get-Module $ModuleName -ListAvailable | Select -First 1 + if(($AzSKPre | Measure-Object).Count -eq 0) + { + WriteMessage "AzSKPre config not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + $AzSKPreConfigPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "AzSK.Pre.json" -Recurse + $AzSKPreConfigContent = Get-Content -Path $AzSKPreConfigPath.FullName | ConvertFrom-Json + if($AzSKPreConfigContent.CurrentVersionForOrg -ne $LatestAzSKVersion.Version.ToString()) + { + WriteMessage "Warning: Your Org policy is configured with older AzSK version[$($AzSKPreConfigContent.CurrentVersionForOrg)]. Consider updating it to latest stable available version [$($LatestAzSKVersion.Version.Tostring())]" $([MessageType]::Warning) + } + } + #endregion + + + #region Check 03: Validate installer file + $Installer = Get-ChildItem -Path $PolicyCopyFolderPath -Include "$($ModuleName)-EasyInstaller.ps1" -Recurse + if(($Installer | Measure-Object).Count -eq 0) + { + WriteMessage "Installer not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating installer file..." $([MessageType]::Info) + $InstallerContent = Get-Content -Path $($Installer.FullName) + $AzSKConfig = $policyBlobslist | Where-Object {$_.Name -like "*AzSK.json*"} + + #Validate OnlinePolicyStoreUrl + $pattern = 'OnlinePolicyStoreUrl = "(.*?)"' + $InstallerPolicyUrl = GetSubString $InstallerContent $pattern + + $policyContainerUrl= $AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + "/```$(```$Version)/```$(```$FileName)" + if($policyContainerUrl -and $InstallerPolicyUrl -notlike "*$policyContainerUrl*" ) + { + WriteMessage "Property Name: [OnlinePolicyStoreUrl]" $([MessageType]::Info) + $InstallerContent=$InstallerContent.Replace($InstallerPolicyUrl,($AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + "/```$(```$Version)/```$(```$FileName)" + $sasToken )) + } + + #Validate AutoUpdateCommand command + $pattern = 'AutoUpdateCommand = "(.*?)"' + $autoUpdateCommandUrl = GetSubString $InstallerContent $pattern + $Installerblob = $policyBlobslist | Where-Object {$_.Name -like "*AzSK-EasyInstaller.ps1*"} + $installerUrl = $Installerblob.ICloudBlob.Uri.AbsoluteUri + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex" + if($autoUpdateCommandUrl -notlike "*$installerUrl*" ) + { + WriteMessage "Property Name: [AutoUpdateCommand]" $([MessageType]::Info) + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex"; + $InstallerContent=$InstallerContent.Replace($autoUpdateCommandUrl,$IWRCommand) + } + + + #Validate AzSKConfigURL + $pattern = 'AzSKConfigURL = "(.*?)"' + $InstallerAzSKPreUrl = GetSubString $InstallerContent $pattern + + $AzSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + if($InstallerAzSKPreUrl -notlike "*$AzSKPreUrl*") + { + WriteMessage "Property Name: [AzSKConfigURL]" $([MessageType]::Info) + $AzSKPreUrl = $AzSKPreUrl + $sasToken + $InstallerContent=$InstallerContent.Replace($InstallerAzSKPreUrl,$AzSKPreUrl) + } + + Out-File -InputObject $InstallerContent -Force -FilePath $($Installer.FullName) -Encoding utf8 + WriteMessage "Completed updating installer file..." $([MessageType]::Update) + } + #endregion + + #region Check 05: Validate CoreSetup + $RunbookCoreSetupPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "RunbookCoreSetup.ps1" -Recurse + $RunbookCoreSetup = $policyBlobslist | Where-Object {$_.Name -like "*RunbookCoreSetup.ps1*"} + if(($RunbookCoreSetupPath | Measure-Object).Count -eq 0) + { + WriteMessage "RunbookCoreSetup not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating runbookCoreSetup file..." $([MessageType]::Info) + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath.FullName + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + $AzSkVersionForOrgUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if([string]::IsNullOrEmpty($coreSetupAzSkVersionForOrgUrl) ) + { + WriteMessage "Warning:Org policy contains older version of RunbookCoreSetup.ps1 and RunbookScanAgent.ps1.`nWould you like to update it with latest version(Y/N):" $([MessageType]::Warning) + $answer= Read-Host + if($answer.ToLower() -eq "y" ) + { + #Take latest + WriteMessage "Copying latest version of 'RunbookCoreSetup.ps1'..." $([MessageType]::Info) + $RunbookUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookCoreSetup.ps1" + + IWR -Uri $RunbookUrl -OutFile $($RunbookCoreSetupPath.FullName) + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath.FullName + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + WriteMessage "Copying latest version of 'RunbookScanAgent.ps1'..." $([MessageType]::Info) + $RunbookUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookScanAgent.ps1" + $RunbookScanAgentPath =Get-ChildItem -Path $PolicyCopyFolderPath -Include "RunbookScanAgent.ps1" -Recurse + IWR -Uri $RunbookUrl -OutFile $($RunbookScanAgentPath.FullName) + + } + else + { + WriteMessage "Skipping RunbookCoreSetup and RunbookScanAgent updates." $([MessageType]::Info) + } + } + if($coreSetupAzSkVersionForOrgUrl -ne "Not Available" -and $coreSetupAzSkVersionForOrgUrl -notlike "*$AzSkVersionForOrgUrl*" ) + { + $AzSkVersionForOrgUrl += $sasToken + WriteMessage "Property Name: [AzSKVersionForOrg]" $([MessageType]::Info) + $RunbookCoreSetupContent = $RunbookCoreSetupContent.Replace($coreSetupAzSkVersionForOrgUrl,$AzSkVersionForOrgUrl) + } + Out-File -InputObject $RunbookCoreSetupContent -Force -FilePath $($RunbookCoreSetupPath.FullName) -Encoding utf8 + WriteMessage "Completed updating runbookCoreSetup file..." $([MessageType]::Update) + } + #endregion + + #region Check 06: Validate AzSKConfig + $AzSKConfigPath = Get-ChildItem -Path $PolicyCopyFolderPath -Include "AzSK.json" -Recurse + if(($AzSKConfigPath | Measure-Object).Count -eq 0) + { + WriteMessage "AzSK config not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + } + else + { + WriteMessage "Updating AzSKConfig file..." $([MessageType]::Info) + $AzSKConfigContent = Get-Content -Path $AzSKConfigPath.FullName | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $RunbookCoreSetupUrl = $RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri + + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'CASetupRunbookURL' $RunbookCoreSetupUrl + if($IsPropertyModified) + { + $AzSKConfigContent.CASetupRunbookURL = $RunbookCoreSetupUrl + $sasToken + WriteMessage "Warning: CASetupRunbookURL is updated with latest Org policy CA setup url.`nYou need to run Update-AzSKContinuousAssurance -SubscriptionId on all installed CA's." $([MessageType]::Warning) + } + + #Validate ControlTelemetryKey + $appInsightResource= Get-AzApplicationInsights -ResourceGroupName $appInsight.ResourceGroupName -Name $appInsight.Name + $InstrumentationKey = $appInsightResource.InstrumentationKey + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'ControlTelemetryKey' $InstrumentationKey + + $azSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'AzSKConfigURL' $azSKPreUrl + if($IsPropertyModified) + { + $AzSKConfigContent.AzSKConfigURL = $azSKPreUrl + $sasToken + } + + #Validate PolicyOrgName + if(-not $AzSKConfigContent.PolicyOrgName -and [string]::IsNullOrEmpty($AzSKConfigContent.PolicyOrgName) ) + { + if(-not [string]::IsNullOrEmpty($AzSKConfigContent.PolicyMessage)) + { + $pattern = 'using (.*?) policy' + $OrgName = GetSubString $($AzSKConfigContent.PolicyMessage) $pattern + if(-not [string]::IsNullOrEmpty($OrgName)) + { + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'PolicyOrgName' $OrgName + } + } + } + + #Validate Installation command + $Installerblob = $policyBlobslist | Where-Object {$_.Name -like "*AzSK-EasyInstaller.ps1*"} + $installerUrl = $Installerblob.ICloudBlob.Uri.AbsoluteUri + $IWRCommand = "iwr '$($installerUrl)' -UseBasicParsing | iex"; + $IsPropertyModified = AddPropertyIfNotExists $AzSKConfigContent 'InstallationCommand' $IWRCommand + + + $AzSKConfigContent | ConvertTo-Json -Depth 10 | Out-File -Force -FilePath $($AzSKConfigPath.FullName) -Encoding utf8 + WriteMessage "Completed updating AzSKConfig file..." $([MessageType]::Update) + } + #region Upload updated configurations to policy store + WriteMessage "Uploading updated configurations to policy store..." $([MessageType]::Info) + Get-ChildItem -Path $PolicyCopyFolderPath | ForEach-Object { + $ContainerName= $_.Name + $directoryList = Get-ChildItem -Path $_.FullName -Recurse -Directory + if(($directoryList | Measure-Object).Count -gt 0) + { + Get-ChildItem -Path $_.FullName -Recurse -Directory | ForEach-Object { + $blobPath= $_.Name + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + } + else + { + $blobPath = [string]::Empty + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + + } + + #endregion + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Policy updated successfully." $([MessageType]::Update) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Updated policy folder path: $PolicyCopyFolderPath" $([MessageType]::Info) + WriteMessage "Backup policy folder path: $PolicyBackupFolderPath" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "******************Instructions to validate policy updates************************" $([MessageType]::Warning) + WriteMessage "`nNow policy has been updated with latest configurations. You can perform below steps to smoke test policy configurations" $([MessageType]::Info) + WriteMessage "`t 1. Run installer(IWR) and validate if it is able to install AzSK successfully." $([MessageType]::Info) + WriteMessage "`t`t $IWRCommand" $([MessageType]::Update) + WriteMessage "`t 2. Run scan command in local machine and validate there is no exceptions" $([MessageType]::Info) + WriteMessage "`t`t Get-AzSKSubscriptionSecurityStatus -SubscriptionId $SubscriptionId" $([MessageType]::Update) + WriteMessage "`t 3. Trigger CA runbook and check if job gets executed and scans are logged in storage account [$($policyStore.Name)]" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "********************Must steps after policy validation**************************" $([MessageType]::Warning) + WriteMessage "`n`t If one of the above validation step is failing, you can restore policy settings with the help of backup using same script with parameter RestoreFromBackup)." $([MessageType]::Info) + WriteMessage "`t If all steps are passing, you can copy these latest updated policy configurations to your Org policy folder which was created at time of policy installation and used to updated policy " $([MessageType]::Info) + WriteMessage "`t Source Path : [$PolicyCopyFolderPath] Destination(Default) Path : [/AzSK-[OrgName]-Policy/]" $([MessageType]::Info) + WriteMessage "`t [policies\3.1803.0] ----> [Config]" $([MessageType]::Info) + WriteMessage "`t [policies\1.0.0] ----> [CA-Runbook]" $([MessageType]::Info) + WriteMessage "`t [installer] ----> [Installer]" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "================================================================================" + } + catch + { + WriteMessage "Exception occured during policy update... $($_.Tostring())" $([MessageType]::Error) + } + + #endregion + +} +else +{ + if( Test-Path $PolicyBackupFolderPath) + { + $backupContent= Get-ChildItem -Path $PolicyBackupFolderPath + if(($backupContent | Measure-Object).Count -eq 0) + { + WriteMessage "Backup folder does not contains any files." $([MessageType]::Error) + return + } + else + { + WriteMessage "Uploading configurations from backup folder to policy store..." $([MessageType]::Info) + $policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName + #Check if poliy store is present + $policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if(($policyStore | Measure-Object).Count -eq 0) + { + WriteMessage "Policy storage account not found. Please re-run the Org policy setup or update cmdlet to fix this issue." $([MessageType]::Error) + return + } + $PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name + $currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https + Get-ChildItem -Path $PolicyBackupFolderPath| ForEach-Object { + $ContainerName= $_.Name + $directoryList = Get-ChildItem -Path $_.FullName -Recurse -Directory + if(($directoryList | Measure-Object).Count -gt 0) + { + Get-ChildItem -Path $_.FullName -Recurse -Directory | ForEach-Object { + $blobPath= $_.Name + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + } + else + { + $blobPath = [string]::Empty + $filesToUpload = Get-ChildItem -Path $_.FullName -Recurse -File + UploadFilesToBlob $currentContext $ContainerName $blobPath $filesToUpload $true + } + + } + + #endregion + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Policy updated successfully." $([MessageType]::Update) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Please perform below tasks to validate successful update of policy from backup folder" $([MessageType]::Info) + WriteMessage "`t 1. Run installer(IWR) and validate if it is able to install AzSK successfully" $([MessageType]::Info) + WriteMessage "`t 2. Run scan command in local machine with Org policy and validate there is no exceptions" $([MessageType]::Info) + WriteMessage "`t 3. Run CA runbook and check if job gets executed and scan results are logged in storage account" $([MessageType]::Info) + WriteMessage "`t 4. If any of above steps is failing after policy update from backup. You can contact support team to resolve the issue" $([MessageType]::Info) + WriteMessage "================================================================================" $([MessageType]::Info) + } + + } + else + { + WriteMessage "Backup folder does not exists" $([MessageType]::Warning) + } +} diff --git a/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.ps1.txt b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.ps1.txt new file mode 100644 index 00000000..68a58e70 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.ps1.txt @@ -0,0 +1,652 @@ +#Script to validate health of Org Policy +Param( + +[string] +[Parameter(Mandatory = $true)] + $SubscriptionId, + +[string] +[Parameter(Mandatory = $true)] +$PolicyResourceGroupName +) + + #Constants + $ModuleName = "AzSK" + $BlankSubId = "00000000-0000-0000-0000-000000000000" + $RepoName = "PSGallery" + + #CA Constants + $caResourceGroupName="AzSKRG" + $automationAccountName="AzSKContinuousAssurance" + $runbookName="Continuous_Assurance_Runbook" + + + #Create log file + $LogFolderPath= $Env:LOCALAPPDATA + "\Microsoft\" + $ModuleName+ "Logs\PolicyHealthCheck\" + + $LogFilePath = $LogFolderPath+ "PolicyHealthCheck$(Get-Date -format "yyyyMMdd_HHmmss").log" + + if(-not (Test-Path -Path $LogFolderPath)) + { + mkdir -Path $LogFolderPath -Force | Out-Null + } + + New-Item $LogFilePath | Out-Null + + #Login and Set context to policy subscription + function Login + { + $currentContext = Get-AzContext + if((-not $currentContext) -or ($currentContext -and ((-not $currentContext.Subscription -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) ` + -or -not $currentContext.Account))) + { + WriteMessage "No active Azure login session found. Initiating login flow..." + + if($this.SubscriptionContext.SubscriptionId -ne $BlankSubId) + { + $rmLogin = Connect-AzAccount -SubscriptionId $SubscriptionId + } + else + { + $rmLogin = Connect-AzAccount + } + + if($rmLogin) + { + $currentContext = $rmLogin.Context; + } + } + + if($currentContext -and $currentContext.Subscription -and $currentContext.Subscription.Id) + { + if(($currentContext.Subscription.Id -ne $SubscriptionId) -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) + { + $currentContext = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop + + + # $currentContext will contain the desired subscription (or $null if id is wrong or no permission) + if ($null -eq $currentContext) + { + throw [SuppressedException] ("Invalid Subscription Id [" + $this.SubscriptionContext.SubscriptionId + "]") + } + } + } +} + #Login End + +function GetSubString($CotentString, $Pattern ) +{ + return $result = [regex]::match($CotentString, $pattern).Groups[1].Value +} + +function IsStringEmpty($String) +{ + if([string]::IsNullOrEmpty($String)) + { + return "Not Available" + } + else + { + $String= $String.Split("?")[0] + return $String + } +} + + +enum MessageType +{ + Error + Warning + Info + Update + Default +} + +function WriteMessage([string] $message,[string] $messageType) +{ + if(-not $message) + { + return; + } + + $colorCode = [System.ConsoleColor]::White + + switch($messageType) + { + ([MessageType]::Error) { + $colorCode = [System.ConsoleColor]::Red + } + ([MessageType]::Warning) { + $colorCode = [System.ConsoleColor]::Yellow + } + ([MessageType]::Info) { + $colorCode = [System.ConsoleColor]::Cyan + } + ([MessageType]::Update) { + $colorCode = [System.ConsoleColor]::Green + } + ([MessageType]::Default) { + $colorCode = [System.ConsoleColor]::White + } + } + Write-Host $message -ForegroundColor $colorCode + Add-Content -Value $message -Path $LogFilePath +} + + +WriteMessage "================================================================================" $([MessageType]::Info) +WriteMessage "Running Org policy health check..." $([MessageType]::Info) +WriteMessage "================================================================================" $([MessageType]::Info) +Login +[PSObject] $PolicyScanOutput = @{} +$PolicyScanOutput.Resources = @{} + + +#Check 01: Presence of Org policy resources +WriteMessage "Check 01: Presence of Org policy resources." $([MessageType]::Info) + +#a. Validate presense of policy resource group +$policyResourceGroup= Get-AzResourceGroup -Name $PolicyResourceGroupName -ErrorAction SilentlyContinue +if(-not $policyResourceGroup) +{ +WriteMessage "`t Missing: Policy resource group" $([MessageType]::Error) +$PolicyScanOutput.Resources.ResourceGroup = $false +return +} +else +{ +$PolicyScanOutput.Resources.ResourceGroup = $true +} + +#b. Validate presense of policy resources storage, app insight and monitoring dashboard +$policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName +#Check if poliy store is present +$policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } +if(($policyStore | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Policy storage account" $([MessageType]::Error) +$PolicyScanOutput.Resources.PolicyStore = $false +return +} +else +{ +$PolicyScanOutput.Resources.PolicyStore = $true +} + +#Check if app insight is present +$appInsight = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Insights/components" } +if(($appInsight | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Policy app insight" $([MessageType]::Error) +$PolicyScanOutput.Resources.AppInsight = $false +} +else +{ +$PolicyScanOutput.Resources.AppInsight = $true +} + +#Check if monitoring dashboard is present +$monitoringDashboard = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Portal/dashboards" } +if(($monitoringDashboard | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Monitoring dashboard" $([MessageType]::Error) +$PolicyScanOutput.Resources.MonitoringDashboard = $false +} +else +{ +$PolicyScanOutput.Resources.MonitoringDashboard = $true +} + +if($PolicyScanOutput.Resources.PolicyStore -and $PolicyScanOutput.Resources.AppInsight -and $PolicyScanOutput.Resources.MonitoringDashboard) +{ +WriteMessage "Status: OK." $([MessageType]::Update) +$PolicyScanOutput.Resources.Status = $true +} +else +{ +WriteMessage "Status: Failed." $([MessageType]::Error) +$PolicyScanOutput.Resources.Status = $false +} +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 02: Presence of mandatory policies +WriteMessage "Check 02: Presence of mandatory policies." $([MessageType]::Info) +$PolicyScanOutput.Policies = @{} +if($PolicyScanOutput.Resources.PolicyStore) +{ +$PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name +$currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https +$containerList = Get-AzStorageContainer -Context $currentContext + +$policyTempFolder = $env:TEMP + "\" + $ModuleName + "\Policies\"; +if(-not (Test-Path "$policyTempFolder")) +{ + mkdir -Path "$policyTempFolder" -ErrorAction Stop | Out-Null +} +else +{ + Remove-Item -Path "$policyTempFolder\*" -Force -Recurse +} + +#Validate presense of installer +$Installer = Get-AzStorageBlobContent -Container "installer" -Blob "$($ModuleName)-EasyInstaller.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +$InstallerPath = $policyTempFolder + "$($ModuleName)-EasyInstaller.ps1" +if(($Installer | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: Installer" $([MessageType]::Error) + $PolicyScanOutput.Policies.Installer = $false +} +else +{ + $PolicyScanOutput.Policies.Installer = $true +} + +#Validate presense of AzSK.Pre.json +$AzSKPre = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/AzSK.Pre.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($AzSKPre | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: AzSKPre Config" $([MessageType]::Error) + $PolicyScanOutput.Policies.AzSKPre = $false +} +else +{ + $PolicyScanOutput.Policies.AzSKPre = $true +} + +$RunbookCoreSetup = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/RunbookCoreSetup.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($RunbookCoreSetup | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookCoreSetup" $([MessageType]::Error) + $PolicyScanOutput.Policies.RunbookCoreSetup = $false +} +else +{ + $PolicyScanOutput.Policies.RunbookCoreSetup = $true +} + +$RunbookScanAgent = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/RunbookScanAgent.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($RunbookScanAgent | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookScanAgent" $([MessageType]::Error) + $PolicyScanOutput.Policies.RunbookScanAgent = $false +} +else +{ + $PolicyScanOutput.Policies.RunbookScanAgent = $true +} + + +$AzSKConfig = Get-AzStorageBlobContent -Container "policies" -Blob "3.1803.0/AzSK.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($AzSKConfig | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookScanAgent" $([MessageType]::Error) + $PolicyScanOutput.Policies.AzSKConfig = $false +} +else +{ + $PolicyScanOutput.Policies.AzSKConfig = $true +} + +$ServerConfigMetadata = Get-AzStorageBlobContent -Container "policies" -Blob "3.1803.0/ServerConfigMetadata.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($ServerConfigMetadata | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: ServerConfigMetadata" $([MessageType]::Error) + $PolicyScanOutput.Policies.ServerConfigMetadata = $false +} +else +{ + $PolicyScanOutput.Policies.ServerConfigMetadata = $true +} + +if($PolicyScanOutput.Policies.Installer -and $PolicyScanOutput.Policies.AzSKPre -and $PolicyScanOutput.Policies.RunbookCoreSetup -and $PolicyScanOutput.Policies.RunbookScanAgent -and $PolicyScanOutput.Policies.AzSKConfig -and $PolicyScanOutput.Policies.ServerConfigMetadata) +{ + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Policies.Status = $true +} +else +{ + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Policies.Status = $false +} +} +else +{ +WriteMessage "Status: Skipped. Policy store not found." $([MessageType]::Info) +$PolicyScanOutput.Policies.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 03: Validate installer file +WriteMessage "Check 03: Check Installer configurations." $([MessageType]::Info) +$PolicyScanOutput.Configurations = @{} +$PolicyScanOutput.Configurations.Installer = @{} +$InstallOutput = $PolicyScanOutput.Configurations.Installer +if($PolicyScanOutput.Policies.Installer) +{ + $InstallerContent = Get-Content -Path $InstallerPath + + #Validate OnlinePolicyStoreUrl + $pattern = 'OnlinePolicyStoreUrl = "(.*?)"' + $InstallerPolicyUrl = GetSubString $InstallerContent $pattern + $policyContainerUrl= $AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + if($InstallerPolicyUrl -like "*$policyContainerUrl*" ) + { + $InstallOutput.PolicyUrl = $true + } + else + { + $InstallOutput.PolicyUrl = $false + WriteMessage "`t Missing Configuration: OnlinePolicyStoreUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($InstallerPolicyUrl))] `n`t Expected: [$(IsStringEmpty($policyContainerUrl))]" $([MessageType]::Info) + } + + #Validate AutoUpdateCommand command + $pattern = 'AutoUpdateCommand = "(.*?)"' + $autoUpdateCommandUrl = GetSubString $InstallerContent $pattern + $installerUrl = $Installer.ICloudBlob.Uri.AbsoluteUri + + if($autoUpdateCommandUrl -like "*$installerUrl*" ) + { + $InstallOutput.AutoUpdateCommandUrl = $true + } + else + { + $InstallOutput.AutoUpdateCommandUrl = $false + WriteMessage "`t Missing Configuration: AutoUpdateCommand" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($autoUpdateCommandUrl))] `n`t Expected: [$(IsStringEmpty($installerUrl))]" $([MessageType]::Info) + } + + #Validate AzSKConfigURL + $pattern = 'AzSKConfigURL = "(.*?)"' + $InstallerAzSKPreUrl = GetSubString $InstallerContent $pattern + $AzSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if($InstallerAzSKPreUrl -like "*$AzSKPreUrl*" ) + { + $InstallOutput.AzSKPreUrl = $true + } + else + { + $InstallOutput.AzSKPreUrl = $false + WriteMessage "`t Missing Configuration: AzSKPreConfigUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($InstallerAzSKPreUrl))] `n`t Expected: [$(IsStringEmpty($AzSKPreUrl))]" $([MessageType]::Info) + } + + if($InstallOutput.PolicyUrl -and $InstallOutput.AutoUpdateCommandUrl -and $InstallOutput.AzSKPreUrl) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $InstallOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $InstallOutput.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. Installer not found." $([MessageType]::Info) + $InstallOutput.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 04: Validate AzSKPre +$PolicyScanOutput.Configurations.AzSKPre = @{} +WriteMessage "Check 04: Check AzSKPre configurations." $([MessageType]::Info) +if($PolicyScanOutput.Policies.AzSKPre) +{ + $AzSKPreConfigPath = $policyTempFolder + "1.0.0\AzSK.Pre.json" + $AzSKPreConfigContent = Get-Content -Path $AzSKPreConfigPath | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $LatestAzSKVersion = Find-Module $ModuleName -Repository $RepoName + if($AzSKPreConfigContent.CurrentVersionForOrg -eq $LatestAzSKVersion.Version.ToString() ) + { + $PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg = $true + } + else + { + $PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg = $true + WriteMessage "`tYou are running on older AzSK version" $([MessageType]::Warning) + WriteMessage "`tCurrentVersion: [$(IsStringEmpty($($AzSKPreConfigContent.CurrentVersionForOrg)))] `n`tLatestVersion: [$(IsStringEmpty($($LatestAzSKVersion.Version.Tostring())))]" $([MessageType]::Warning) + } + + if($PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Configurations.AzSKPre.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Configurations.AzSKPre.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. AzSKPreConfig not found." $([MessageType]::Info) + $PolicyScanOutput.Configurations.AzSKPre.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 05: Validate CoreSetup +$PolicyScanOutput.Configurations.RunbookCoreSetup = @{} +WriteMessage "Check 05: Check RunbookCoreSetup configurations." $([MessageType]::Info) +if($PolicyScanOutput.Policies.RunbookCoreSetup) +{ + $RunbookCoreSetupPath = $policyTempFolder + "1.0.0\RunbookCoreSetup.ps1" + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath + + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + $AzSkVersionForOrgUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if($coreSetupAzSkVersionForOrgUrl -like "*$AzSkVersionForOrgUrl*" ) + { + $PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl = $true + } + else + { + $PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl = $false + WriteMessage "`t Missing Configuration: AzSkVersionForOrgUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($coreSetupAzSkVersionForOrgUrl))] `n`t Expected: [$(IsStringEmpty($AzSkVersionForOrgUrl))]" $([MessageType]::Info) + } + + if($PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. RunbookCoreSetup not found." $([MessageType]::Info) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 06: Validate AzSKConfig +$PolicyScanOutput.Configurations.AzSKConfig = @{} +WriteMessage "Check 06: Check AzSKConfig configurations." $([MessageType]::Info) +$AzSKConfiguOutput = $PolicyScanOutput.Configurations.AzSKConfig +if($PolicyScanOutput.Policies.AzSKConfig) +{ + $AzSKConfigPath = $policyTempFolder + "3.1803.0\AzSK.json" #TODO:Constant + $AzSKConfigContent = Get-Content -Path $AzSKConfigPath | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $RunbookCoreSetupUrl = $RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.CASetupRunbookURL -and $AzSKConfigContent.CASetupRunbookURL -like "*$RunbookCoreSetupUrl*") + { + $AzSKConfiguOutput.CASetupRunbookUrl = $true + } + else + { + $AzSKConfiguOutput.CASetupRunbookUrl = $false + WriteMessage "`t Missing Configuration: CASetupRunbookUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.CASetupRunbookURL)))] `n`t Expected: [$(IsStringEmpty($($RunbookCoreSetupUrl)))]" $([MessageType]::Info) + } + + #Validate ControlTelemetryKey + $appInsightResource= Get-AzApplicationInsights -ResourceGroupName $appInsight.ResourceGroupName -Name $appInsight.Name + $InstrumentationKey = $appInsightResource.InstrumentationKey + + if($AzSKConfigContent.ControlTelemetryKey -and $AzSKConfigContent.ControlTelemetryKey -eq $InstrumentationKey) + { + $AzSKConfiguOutput.ControlTelemetryKey = $true + } + else + { + $AzSKConfiguOutput.ControlTelemetryKey = $false + WriteMessage "`t Missing Configuration: ControlTelemetryKey" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.ControlTelemetryKey)))] `n`t Expected: [$(IsStringEmpty($($InstrumentationKey)))]" $([MessageType]::Info) + } + + # Validate InstallationCommand + $installerUrl = $Installer.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.InstallationCommand -and $AzSKConfigContent.InstallationCommand -like "*$installerUrl*") + { + $AzSKConfiguOutput.InstallationCommand = $true + } + else + { + $AzSKConfiguOutput.InstallationCommand = $false + WriteMessage "`t Missing Configuration: InstallationCommand" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.InstallationCommand)))] `n`t Expected: [$(IsStringEmpty($($installerUrl)))]" $([MessageType]::Info) + } + + + # Validate PolicyOrgName + if($AzSKConfigContent.PolicyOrgName -and -not [string]::IsNullOrEmpty($AzSKConfigContent.PolicyOrgName) ) + { + $PolicyScanOutput.Configurations.AzSKConfig.PolicyOrgName = $true + } + else + { + $AzSKConfiguOutput.PolicyOrgName = $false + WriteMessage "`t Missing Configuration: PolicyOrgName" $([MessageType]::Error) + } + + # Validate AzSKPre Url + $azSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.AzSKConfigURL -and $AzSKConfigContent.AzSKConfigURL -like "*$azSKPreUrl*") + { + $AzSKConfiguOutput.AzSKPreConfigURL = $true + } + else + { + $AzSKConfiguOutput.AzSKPreConfigURL = $false + WriteMessage "`t Missing Configuration: AzSKPreConfigURL" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.AzSKConfigURL)))] `n`t Expected: [$(IsStringEmpty($($azSKPreUrl)))]" $([MessageType]::Info) + } + + if($AzSKConfiguOutput.CASetupRunbookUrl -and $AzSKConfiguOutput.ControlTelemetryKey -and $AzSKConfiguOutput.InstallationCommand -and $AzSKConfiguOutput.PolicyOrgName -and $AzSKConfiguOutput.AzSKPreConfigURL ) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $AzSKConfiguOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $AzSKConfiguOutput.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. AzSKConfig not found." $([MessageType]::Info) + $AzSKConfiguOutput.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) +#Check 07: Validate AzSKConfig +$PolicyScanOutput.Configurations.CARunbook = @{} +$CARunbookOutput= $PolicyScanOutput.Configurations.CARunbook +WriteMessage "Check 07: Check CA runbook configurations." $([MessageType]::Info) + + $azskRG = Get-AzResourceGroup -Name $caResourceGroupName -ErrorAction SilentlyContinue + $automationAccount = Get-AzAutomationAccount -ResourceGroupName $caResourceGroupName -Name $automationAccountName + + if($azskRG -and $automationAccount) + { + $validatedUri= "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$caResourceGroupName/providers/Microsoft.Automation/automationAccounts/$automationAccountName/runbooks/$runbookName/content?api-version=2015-10-31" + + + $accessToken=Get-AzSKAccessToken -ResourceAppIdURI "https://management.core.windows.net/" + $serverFileContent = Invoke-RestMethod ` + -Method GET ` + -Uri $validatedUri ` + -Headers @{"Authorization" = "Bearer $accessToken"} ` + -UseBasicParsing + + #Check if OSS CoreSetup is refered in runbooks + $ossCoreSetupUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookCoreSetup.ps1" + $ossPolicyUrl = "https://azsdkossep.azureedge.net/```$Version/```$FileName" + + + if($serverFileContent.Contains($ossCoreSetupUrl)) + { + $CARunbookOutput.CoreSetupURL = $false + WriteMessage "`t Missing Configuration : [CoreSetupSrcUrl]" $([MessageType]::Error) + WriteMessage "`t Actual: $(IsStringEmpty($($ossCoreSetupUrl))) `n`t Expected: $(IsStringEmpty($($RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri)))" $([MessageType]::Info) + + } + else + { + $CARunbookOutput.CoreSetupURL = $true + } + + if($serverFileContent.Contains($ossPolicyUrl)) + { + $CARunbookOutput.PolicyURL = $false + WriteMessage "`t Missing Configuration : [CoreSetupSrcUrl]" $([MessageType]::Error) + $ExpectedUrl = $RunbookCoreSetup.ICloudBlob.Container.Uri.AbsoluteUri+"/```$Version/```$FileName" + WriteMessage "`t Actual: [$(IsStringEmpty($($ossPolicyUrl)))] `n`t Expected: [$(IsStringEmpty($ExpectedUrl))]" $([MessageType]::Info) + } + else + { + $CARunbookOutput.PolicyURL = $true + } + if($CARunbookOutput.CoreSetupURL -and $CARunbookOutput.PolicyURL) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $CARunbookOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $CARunbookOutput.Status = $true + } + } + else + { + WriteMessage "Status: Skipped. CA not found under resource group [$caResourceGroupName]." $([MessageType]::Info) + $PolicyScanOutput.Configurations.CARunbook.Status = $true + } + + +if(-not $PolicyScanOutput.Resources.Status -or -not $PolicyScanOutput.Policies.Status -or -not $InstallOutput.Status -or -not $PolicyScanOutput.Configurations.AzSKPre.Status -or -not $PolicyScanOutput.Configurations.RunbookCoreSetup.Status -or -not $AzSKConfiguOutput.Status -or -not $CARunbookOutput.Status) +{ + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Your Org policy configuration is not correctly setup.`nReview failed checks and follow suggested remedies at: https://aka.ms/devopskit/orgpolicy/healthcheck . You can contact support team for more details: azsksup@microsoft.com " $([MessageType]::Warning) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) +} +else +{ + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + WriteMessage "Org policy configuration is in healthy state. `nFor other details, please follow guide at: https://aka.ms/devopskit/orgpolicy/healthcheck. You can contact support team for more details: azsksup@microsoft.com" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) +} +WriteMessage "================================================================================" $([MessageType]::Info) + +WriteMessage "Logs have been exported to location: '$LogFilePath'" + diff --git a/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.txt b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.txt new file mode 100644 index 00000000..e69347e3 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.txt @@ -0,0 +1,652 @@ +#Script to validate health of Org Policy +Param( + +[string] +[Parameter(Mandatory = $true)] + $SubscriptionId, + +[string] +[Parameter(Mandatory = $true)] +$PolicyResourceGroupName +) + + #Constants + $ModuleName = "AzSK" + $BlankSubId = "00000000-0000-0000-0000-000000000000" + $RepoName = "PSGallery" + + #CA Constants + $caResourceGroupName="AzSKRG" + $automationAccountName="AzSKContinuousAssurance" + $runbookName="Continuous_Assurance_Runbook" + + + #Create log file + $LogFolderPath= $Env:LOCALAPPDATA + "\Microsoft\" + $ModuleName+ "Logs\PolicyHealthCheck\" + + $LogFilePath = $LogFolderPath+ "PolicyHealthCheck$(Get-Date -format "yyyyMMdd_HHmmss").log" + + if(-not (Test-Path -Path $LogFolderPath)) + { + mkdir -Path $LogFolderPath -Force | Out-Null + } + + New-Item $LogFilePath | Out-Null + + #Login and Set context to policy subscription + function Login + { + $currentContext = Get-AzContext + if((-not $currentContext) -or ($currentContext -and ((-not $currentContext.Subscription -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) ` + -or -not $currentContext.Account))) + { + WriteMessage "No active Azure login session found. Initiating login flow..." + + if($this.SubscriptionContext.SubscriptionId -ne $BlankSubId) + { + $rmLogin = Connect-AzAccount -SubscriptionId $SubscriptionId + } + else + { + $rmLogin = Connect-AzAccount + } + + if($rmLogin) + { + $currentContext = $rmLogin.Context; + } + } + + if($currentContext -and $currentContext.Subscription -and $currentContext.Subscription.Id) + { + if(($currentContext.Subscription.Id -ne $SubscriptionId) -and ($this.SubscriptionContext.SubscriptionId -ne $BlankSubId)) + { + $currentContext = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop + + + # $currentContext will contain the desired subscription (or $null if id is wrong or no permission) + if ($null -eq $currentContext) + { + throw [SuppressedException] ("Invalid Subscription Id [" + $this.SubscriptionContext.SubscriptionId + "]") + } + } + } +} + #Login End + +function GetSubString($CotentString, $Pattern ) +{ + return $result = [regex]::match($CotentString, $pattern).Groups[1].Value +} + +function IsStringEmpty($String) +{ + if([string]::IsNullOrEmpty($String)) + { + return "Not Available" + } + else + { + $String= $String.Split("?")[0] + return $String + } +} + + +enum MessageType +{ + Error + Warning + Info + Update + Default +} + +function WriteMessage([string] $message,[string] $messageType) +{ + if(-not $message) + { + return; + } + + $colorCode = [System.ConsoleColor]::White + + switch($messageType) + { + ([MessageType]::Error) { + $colorCode = [System.ConsoleColor]::Red + } + ([MessageType]::Warning) { + $colorCode = [System.ConsoleColor]::Yellow + } + ([MessageType]::Info) { + $colorCode = [System.ConsoleColor]::Cyan + } + ([MessageType]::Update) { + $colorCode = [System.ConsoleColor]::Green + } + ([MessageType]::Default) { + $colorCode = [System.ConsoleColor]::White + } + } + Write-Host $message -ForegroundColor $colorCode + Add-Content -Value $message -Path $LogFilePath +} + + +WriteMessage "================================================================================" $([MessageType]::Info) +WriteMessage "Running Org policy health check..." $([MessageType]::Info) +WriteMessage "================================================================================" $([MessageType]::Info) +Login +[PSObject] $PolicyScanOutput = @{} +$PolicyScanOutput.Resources = @{} + + +#Check 01: Presence of Org policy resources +WriteMessage "Check 01: Presence of Org policy resources(Policy StorageAccount/ Telemetry AppInsights/Monitoring Dashboard)." $([MessageType]::Info) + +#a. Validate presense of policy resource group +$policyResourceGroup= Get-AzResourceGroup -Name $PolicyResourceGroupName -ErrorAction SilentlyContinue +if(-not $policyResourceGroup) +{ +WriteMessage "`t Missing: Policy resource group" $([MessageType]::Error) +$PolicyScanOutput.Resources.ResourceGroup = $false +return +} +else +{ +$PolicyScanOutput.Resources.ResourceGroup = $true +} + +#b. Validate presense of policy resources storage, app insight and monitoring dashboard +$policyResources= Get-AzResource -ResourceGroupName $policyResourceGroupName +#Check if poliy store is present +$policyStore = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Storage/storageAccounts" } +if(($policyStore | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Policy storage account" $([MessageType]::Error) +$PolicyScanOutput.Resources.PolicyStore = $false +return +} +else +{ +$PolicyScanOutput.Resources.PolicyStore = $true +} + +#Check if app insight is present +$appInsight = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Insights/components" } +if(($appInsight | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Policy app insight" $([MessageType]::Error) +$PolicyScanOutput.Resources.AppInsight = $false +} +else +{ +$PolicyScanOutput.Resources.AppInsight = $true +} + +#Check if monitoring dashboard is present +$monitoringDashboard = $policyResources | Where-Object {$_.ResourceType -eq "Microsoft.Portal/dashboards" } +if(($monitoringDashboard | Measure-Object).Count -eq 0) +{ +WriteMessage "`t Missing: Monitoring dashboard" $([MessageType]::Error) +$PolicyScanOutput.Resources.MonitoringDashboard = $false +} +else +{ +$PolicyScanOutput.Resources.MonitoringDashboard = $true +} + +if($PolicyScanOutput.Resources.PolicyStore -and $PolicyScanOutput.Resources.AppInsight -and $PolicyScanOutput.Resources.MonitoringDashboard) +{ +WriteMessage "Status: OK." $([MessageType]::Update) +$PolicyScanOutput.Resources.Status = $true +} +else +{ +WriteMessage "Status: Failed." $([MessageType]::Error) +$PolicyScanOutput.Resources.Status = $false +} +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 02: Presence of mandatory policies +WriteMessage "Check 02: Presence of mandatory policies(Installer/Runbooks/Configuration Index file)" $([MessageType]::Info) +$PolicyScanOutput.Policies = @{} +if($PolicyScanOutput.Resources.PolicyStore) +{ +$PolicyStoragekey = Get-AzStorageAccountKey -ResourceGroupName $policyStore.ResourceGroupName -Name $policyStore.Name +$currentContext = New-AzStorageContext -StorageAccountName $policyStore.Name -StorageAccountKey $PolicyStoragekey[0].Value -Protocol Https +$containerList = Get-AzStorageContainer -Context $currentContext + +$policyTempFolder = $env:TEMP + "\" + $ModuleName + "\Policies\"; +if(-not (Test-Path "$policyTempFolder")) +{ + mkdir -Path "$policyTempFolder" -ErrorAction Stop | Out-Null +} +else +{ + Remove-Item -Path "$policyTempFolder\*" -Force -Recurse +} + +#Validate presense of installer +$Installer = Get-AzStorageBlobContent -Container "installer" -Blob "$($ModuleName)-EasyInstaller.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +$InstallerPath = $policyTempFolder + "$($ModuleName)-EasyInstaller.ps1" +if(($Installer | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: Installer" $([MessageType]::Error) + $PolicyScanOutput.Policies.Installer = $false +} +else +{ + $PolicyScanOutput.Policies.Installer = $true +} + +#Validate presense of AzSK.Pre.json +$AzSKPre = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/AzSK.Pre.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($AzSKPre | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: AzSKPre Config" $([MessageType]::Error) + $PolicyScanOutput.Policies.AzSKPre = $false +} +else +{ + $PolicyScanOutput.Policies.AzSKPre = $true +} + +$RunbookCoreSetup = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/RunbookCoreSetup.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($RunbookCoreSetup | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookCoreSetup" $([MessageType]::Error) + $PolicyScanOutput.Policies.RunbookCoreSetup = $false +} +else +{ + $PolicyScanOutput.Policies.RunbookCoreSetup = $true +} + +$RunbookScanAgent = Get-AzStorageBlobContent -Container "policies" -Blob "1.0.0/RunbookScanAgent.ps1" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($RunbookScanAgent | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookScanAgent" $([MessageType]::Error) + $PolicyScanOutput.Policies.RunbookScanAgent = $false +} +else +{ + $PolicyScanOutput.Policies.RunbookScanAgent = $true +} + + +$AzSKConfig = Get-AzStorageBlobContent -Container "policies" -Blob "3.1803.0/AzSK.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($AzSKConfig | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: RunbookScanAgent" $([MessageType]::Error) + $PolicyScanOutput.Policies.AzSKConfig = $false +} +else +{ + $PolicyScanOutput.Policies.AzSKConfig = $true +} + +$ServerConfigMetadata = Get-AzStorageBlobContent -Container "policies" -Blob "3.1803.0/ServerConfigMetadata.json" -Context $currentContext -Destination $policyTempFolder -Force -ErrorAction SilentlyContinue +if(($ServerConfigMetadata | Measure-Object).Count -eq 0) +{ + WriteMessage "`t Missing: ServerConfigMetadata" $([MessageType]::Error) + $PolicyScanOutput.Policies.ServerConfigMetadata = $false +} +else +{ + $PolicyScanOutput.Policies.ServerConfigMetadata = $true +} + +if($PolicyScanOutput.Policies.Installer -and $PolicyScanOutput.Policies.AzSKPre -and $PolicyScanOutput.Policies.RunbookCoreSetup -and $PolicyScanOutput.Policies.RunbookScanAgent -and $PolicyScanOutput.Policies.AzSKConfig -and $PolicyScanOutput.Policies.ServerConfigMetadata) +{ + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Policies.Status = $true +} +else +{ + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Policies.Status = $false +} +} +else +{ +WriteMessage "Status: Skipped. Policy store not found." $([MessageType]::Info) +$PolicyScanOutput.Policies.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 03: Validate installer contains +WriteMessage "Check 03: Check Installer contains policy url/AzSK Version For Org (AzSK-EasyInstaller.ps1)." $([MessageType]::Info) +$PolicyScanOutput.Configurations = @{} +$PolicyScanOutput.Configurations.Installer = @{} +$InstallOutput = $PolicyScanOutput.Configurations.Installer +if($PolicyScanOutput.Policies.Installer) +{ + $InstallerContent = Get-Content -Path $InstallerPath + + #Validate OnlinePolicyStoreUrl + $pattern = 'OnlinePolicyStoreUrl = "(.*?)"' + $InstallerPolicyUrl = GetSubString $InstallerContent $pattern + $policyContainerUrl= $AzSKConfig.ICloudBlob.Container.Uri.AbsoluteUri + if($InstallerPolicyUrl -like "*$policyContainerUrl*" ) + { + $InstallOutput.PolicyUrl = $true + } + else + { + $InstallOutput.PolicyUrl = $false + WriteMessage "`t Missing Configuration: OnlinePolicyStoreUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($InstallerPolicyUrl))] `n`t Expected: [$(IsStringEmpty($policyContainerUrl))]" $([MessageType]::Info) + } + + #Validate AutoUpdateCommand command + $pattern = 'AutoUpdateCommand = "(.*?)"' + $autoUpdateCommandUrl = GetSubString $InstallerContent $pattern + $installerUrl = $Installer.ICloudBlob.Uri.AbsoluteUri + + if($autoUpdateCommandUrl -like "*$installerUrl*" ) + { + $InstallOutput.AutoUpdateCommandUrl = $true + } + else + { + $InstallOutput.AutoUpdateCommandUrl = $false + WriteMessage "`t Missing Configuration: AutoUpdateCommand" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($autoUpdateCommandUrl))] `n`t Expected: [$(IsStringEmpty($installerUrl))]" $([MessageType]::Info) + } + + #Validate AzSKConfigURL + $pattern = 'AzSKConfigURL = "(.*?)"' + $InstallerAzSKPreUrl = GetSubString $InstallerContent $pattern + $AzSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if($InstallerAzSKPreUrl -like "*$AzSKPreUrl*" ) + { + $InstallOutput.AzSKPreUrl = $true + } + else + { + $InstallOutput.AzSKPreUrl = $false + WriteMessage "`t Missing Configuration: AzSKPreConfigUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($InstallerAzSKPreUrl))] `n`t Expected: [$(IsStringEmpty($AzSKPreUrl))]" $([MessageType]::Info) + } + + if($InstallOutput.PolicyUrl -and $InstallOutput.AutoUpdateCommandUrl -and $InstallOutput.AzSKPreUrl) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $InstallOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $InstallOutput.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. Installer not found." $([MessageType]::Info) + $InstallOutput.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 04: Validate AzSKPre +$PolicyScanOutput.Configurations.AzSKPre = @{} +WriteMessage "Check 04: Check AzSK Version configured for Org(AzSK.Pre.json)." $([MessageType]::Info) +if($PolicyScanOutput.Policies.AzSKPre) +{ + $AzSKPreConfigPath = $policyTempFolder + "1.0.0\AzSK.Pre.json" + $AzSKPreConfigContent = Get-Content -Path $AzSKPreConfigPath | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $LatestAzSKVersion = Find-Module $ModuleName -Repository $RepoName + if($AzSKPreConfigContent.CurrentVersionForOrg -eq $LatestAzSKVersion.Version.ToString() ) + { + $PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg = $true + } + else + { + $PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg = $true + WriteMessage "`tYou are running on older AzSK version" $([MessageType]::Warning) + WriteMessage "`tCurrentVersion: [$(IsStringEmpty($($AzSKPreConfigContent.CurrentVersionForOrg)))] `n`tLatestVersion: [$(IsStringEmpty($($LatestAzSKVersion.Version.Tostring())))]" $([MessageType]::Warning) + } + + if($PolicyScanOutput.Configurations.AzSKPre.CurrentVersionForOrg) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Configurations.AzSKPre.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Configurations.AzSKPre.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. AzSKPreConfig not found." $([MessageType]::Info) + $PolicyScanOutput.Configurations.AzSKPre.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 05: Validate CoreSetup +$PolicyScanOutput.Configurations.RunbookCoreSetup = @{} +WriteMessage "Check 05: Check continueous assurrance RunbookCoreSetup contains reference for Org version(RunbookCoreSetup.ps1)." $([MessageType]::Info) +if($PolicyScanOutput.Policies.RunbookCoreSetup) +{ + $RunbookCoreSetupPath = $policyTempFolder + "1.0.0\RunbookCoreSetup.ps1" + $RunbookCoreSetupContent = Get-Content -Path $RunbookCoreSetupPath + + #Validate AzSkVersionForOrgUrl command + $pattern = 'azskVersionForOrg = "(.*?)"' + $coreSetupAzSkVersionForOrgUrl = GetSubString $RunbookCoreSetupContent $pattern + $AzSkVersionForOrgUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + + if($coreSetupAzSkVersionForOrgUrl -like "*$AzSkVersionForOrgUrl*" ) + { + $PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl = $true + } + else + { + $PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl = $false + WriteMessage "`t Missing Configuration: AzSkVersionForOrgUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($coreSetupAzSkVersionForOrgUrl))] `n`t Expected: [$(IsStringEmpty($AzSkVersionForOrgUrl))]" $([MessageType]::Info) + } + + if($PolicyScanOutput.Configurations.RunbookCoreSetup.AzSkVersionForOrgUrl) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. RunbookCoreSetup not found." $([MessageType]::Info) + $PolicyScanOutput.Configurations.RunbookCoreSetup.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + +#Check 06: Validate AzSKConfig +$PolicyScanOutput.Configurations.AzSKConfig = @{} +WriteMessage "Check 06: Check AzSKConfig configurations(AzSK.json)." $([MessageType]::Info) +$AzSKConfiguOutput = $PolicyScanOutput.Configurations.AzSKConfig +if($PolicyScanOutput.Policies.AzSKConfig) +{ + $AzSKConfigPath = $policyTempFolder + "3.1803.0\AzSK.json" #TODO:Constant + $AzSKConfigContent = Get-Content -Path $AzSKConfigPath | ConvertFrom-Json + + #Validate CurrentVersionForOrg + $RunbookCoreSetupUrl = $RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.CASetupRunbookURL -and $AzSKConfigContent.CASetupRunbookURL -like "*$RunbookCoreSetupUrl*") + { + $AzSKConfiguOutput.CASetupRunbookUrl = $true + } + else + { + $AzSKConfiguOutput.CASetupRunbookUrl = $false + WriteMessage "`t Missing Configuration: CASetupRunbookUrl" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.CASetupRunbookURL)))] `n`t Expected: [$(IsStringEmpty($($RunbookCoreSetupUrl)))]" $([MessageType]::Info) + } + + #Validate ControlTelemetryKey + $appInsightResource= Get-AzApplicationInsights -ResourceGroupName $appInsight.ResourceGroupName -Name $appInsight.Name + $InstrumentationKey = $appInsightResource.InstrumentationKey + + if($AzSKConfigContent.ControlTelemetryKey -and $AzSKConfigContent.ControlTelemetryKey -eq $InstrumentationKey) + { + $AzSKConfiguOutput.ControlTelemetryKey = $true + } + else + { + $AzSKConfiguOutput.ControlTelemetryKey = $false + WriteMessage "`t Missing Configuration: ControlTelemetryKey" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.ControlTelemetryKey)))] `n`t Expected: [$(IsStringEmpty($($InstrumentationKey)))]" $([MessageType]::Info) + } + + # Validate InstallationCommand + $installerUrl = $Installer.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.InstallationCommand -and $AzSKConfigContent.InstallationCommand -like "*$installerUrl*") + { + $AzSKConfiguOutput.InstallationCommand = $true + } + else + { + $AzSKConfiguOutput.InstallationCommand = $false + WriteMessage "`t Missing Configuration: InstallationCommand" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.InstallationCommand)))] `n`t Expected: [$(IsStringEmpty($($installerUrl)))]" $([MessageType]::Info) + } + + + # Validate PolicyOrgName + if($AzSKConfigContent.PolicyOrgName -and -not [string]::IsNullOrEmpty($AzSKConfigContent.PolicyOrgName) ) + { + $PolicyScanOutput.Configurations.AzSKConfig.PolicyOrgName = $true + } + else + { + $AzSKConfiguOutput.PolicyOrgName = $false + WriteMessage "`t Missing Configuration: PolicyOrgName" $([MessageType]::Error) + } + + # Validate AzSKPre Url + $azSKPreUrl = $AzSKPre.ICloudBlob.Uri.AbsoluteUri + if($AzSKConfigContent.AzSKConfigURL -and $AzSKConfigContent.AzSKConfigURL -like "*$azSKPreUrl*") + { + $AzSKConfiguOutput.AzSKPreConfigURL = $true + } + else + { + $AzSKConfiguOutput.AzSKPreConfigURL = $false + WriteMessage "`t Missing Configuration: AzSKPreConfigURL" $([MessageType]::Error) + WriteMessage "`t Actual: [$(IsStringEmpty($($AzSKConfigContent.AzSKConfigURL)))] `n`t Expected: [$(IsStringEmpty($($azSKPreUrl)))]" $([MessageType]::Info) + } + + if($AzSKConfiguOutput.CASetupRunbookUrl -and $AzSKConfiguOutput.ControlTelemetryKey -and $AzSKConfiguOutput.InstallationCommand -and $AzSKConfiguOutput.PolicyOrgName -and $AzSKConfiguOutput.AzSKPreConfigURL ) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $AzSKConfiguOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $AzSKConfiguOutput.Status = $false + } +} +else +{ + WriteMessage "Status: Skipped. AzSKConfig not found." $([MessageType]::Info) + $AzSKConfiguOutput.Status = $false +} + +WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) +#Check 07: Validate AzSKConfig +$PolicyScanOutput.Configurations.CARunbook = @{} +$CARunbookOutput= $PolicyScanOutput.Configurations.CARunbook +WriteMessage "Check 07: Check CA runbook referring to Org Policy URL" $([MessageType]::Info) + + $azskRG = Get-AzResourceGroup -Name $caResourceGroupName -ErrorAction SilentlyContinue + $automationAccount = Get-AzAutomationAccount -ResourceGroupName $caResourceGroupName -Name $automationAccountName + + if($azskRG -and $automationAccount) + { + $validatedUri= "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$caResourceGroupName/providers/Microsoft.Automation/automationAccounts/$automationAccountName/runbooks/$runbookName/content?api-version=2015-10-31" + + + $accessToken=Get-AzSKAccessToken -ResourceAppIdURI "https://management.core.windows.net/" + $serverFileContent = Invoke-RestMethod ` + -Method GET ` + -Uri $validatedUri ` + -Headers @{"Authorization" = "Bearer $accessToken"} ` + -UseBasicParsing + + #Check if OSS CoreSetup is refered in runbooks + $ossCoreSetupUrl = "https://azsdkossep.azureedge.net/1.0.0/RunbookCoreSetup.ps1" + $ossPolicyUrl = "https://azsdkossep.azureedge.net/```$Version/```$FileName" + + + if($serverFileContent.Contains($ossCoreSetupUrl)) + { + $CARunbookOutput.CoreSetupURL = $false + WriteMessage "`t Missing Configuration : [CoreSetupSrcUrl]" $([MessageType]::Error) + WriteMessage "`t Actual: $(IsStringEmpty($($ossCoreSetupUrl))) `n`t Expected: $(IsStringEmpty($($RunbookCoreSetup.ICloudBlob.Uri.AbsoluteUri)))" $([MessageType]::Info) + + } + else + { + $CARunbookOutput.CoreSetupURL = $true + } + + if($serverFileContent.Contains($ossPolicyUrl)) + { + $CARunbookOutput.PolicyURL = $false + WriteMessage "`t Missing Configuration : [CoreSetupSrcUrl]" $([MessageType]::Error) + $ExpectedUrl = $RunbookCoreSetup.ICloudBlob.Container.Uri.AbsoluteUri+"/```$Version/```$FileName" + WriteMessage "`t Actual: [$(IsStringEmpty($($ossPolicyUrl)))] `n`t Expected: [$(IsStringEmpty($ExpectedUrl))]" $([MessageType]::Info) + } + else + { + $CARunbookOutput.PolicyURL = $true + } + if($CARunbookOutput.CoreSetupURL -and $CARunbookOutput.PolicyURL) + { + WriteMessage "Status: OK." $([MessageType]::Update) + $CARunbookOutput.Status = $true + } + else + { + WriteMessage "Status: Failed." $([MessageType]::Error) + $CARunbookOutput.Status = $true + } + } + else + { + WriteMessage "Status: Skipped. CA not found under resource group [$caResourceGroupName]." $([MessageType]::Info) + $PolicyScanOutput.Configurations.CARunbook.Status = $true + } + + +if(-not $PolicyScanOutput.Resources.Status -or -not $PolicyScanOutput.Policies.Status -or -not $InstallOutput.Status -or -not $PolicyScanOutput.Configurations.AzSKPre.Status -or -not $PolicyScanOutput.Configurations.RunbookCoreSetup.Status -or -not $AzSKConfiguOutput.Status -or -not $CARunbookOutput.Status) +{ + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) + WriteMessage "Your Org policy configuration is not correctly setup.`nReview failed checks and follow suggested remedies at: https://aka.ms/devopskit/orgpolicy/healthcheck . You can contact support team for more details: azsksup@microsoft.com " $([MessageType]::Warning) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Warning) +} +else +{ + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) + WriteMessage "Org policy configuration is in healthy state. `nFor other details, please follow guide at: https://aka.ms/devopskit/orgpolicy/healthcheck. You can contact support team for more details: azsksup@microsoft.com" $([MessageType]::Info) + WriteMessage "--------------------------------------------------------------------------------" $([MessageType]::Info) +} +WriteMessage "================================================================================" $([MessageType]::Info) + +WriteMessage "Logs have been exported to location: '$LogFilePath'" + diff --git a/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyPushOrgMappingEvents.txt b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyPushOrgMappingEvents.txt new file mode 100644 index 00000000..1dc648e7 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyPushOrgMappingEvents.txt @@ -0,0 +1,126 @@ +#Telemetry functions -- start here +function SetCommonProperties([psobject] $EventObj) { + $notAvailable = "NA" + +} + +function GetEventBaseObject([string] $EventName) { + $eventObj = "" | Select-Object data, iKey, name, tags, time + $eventObj.iKey = $telemetryKey + $eventObj.name = "Microsoft.ApplicationInsights." + $telemetryKey.Replace("-", "") + ".Event" + $eventObj.time = [datetime]::UtcNow.ToString("o") + + $eventObj.tags = "" | Select-Object ai.internal.sdkVersion + $eventObj.tags.'ai.internal.sdkVersion' = "dotnet: 2.1.0.26048" + + $eventObj.data = "" | Select-Object baseData, baseType + $eventObj.data.baseType = "EventData" + $eventObj.data.baseData = "" | Select-Object ver, name, measurements, properties + + $eventObj.data.baseData.ver = 2 + $eventObj.data.baseData.name = $EventName + + $eventObj.data.baseData.measurements = New-Object 'system.collections.generic.dictionary[string,double]' + $eventObj.data.baseData.properties = New-Object 'system.collections.generic.dictionary[string,string]' + + return $eventObj; +} + +function PublishEvent([string] $EventName, [hashtable] $Properties, [hashtable] $Metrics) { + try { + #return if telemetry key is empty + if ([string]::IsNullOrWhiteSpace($telemetryKey)) { return; }; + + $eventObj = GetEventBaseObject -EventName $EventName + SetCommonProperties -EventObj $eventObj + + if ($null -ne $Properties) { + $Properties.Keys | ForEach-Object { + try { + if (!$eventObj.data.baseData.properties.ContainsKey($_)) { + $eventObj.data.baseData.properties.Add($_ , $Properties[$_].ToString()) + } + } + catch + { + # Left blank intentionally. + # Error while sending alert event to telemetry. No need to break the execution. + } + } + } + if ($null -ne $Metrics) { + $Metrics.Keys | ForEach-Object { + try { + $metric = $Metrics[$_] -as [double] + if (!$eventObj.data.baseData.measurements.ContainsKey($_) -and $null -ne $metric) { + $eventObj.data.baseData.measurements.Add($_ , $Metrics[$_]) + } + } + catch { + # Left blank intentionally. + # Error while sending alert event to telemetry. No need to break the execution. + } + } + } + + $eventJson = ConvertTo-Json $eventObj -Depth 100 -Compress + $eventObj + Invoke-WebRequest -Uri "https://dc.services.visualstudio.com/v2/track" ` + -Method Post ` + -ContentType "application/x-json-stream" ` + -Body $eventJson ` + -UseBasicParsing | Out-Null + } + catch { + # Left blank intentionally. + # Error while sending alert event to telemetry. No need to break the execution. + } +} + +#Telemetry functions -- ends here + + +function SendOrgDetailsEvent([string] $OrgMappingFilePath, [string] $InstrumentationKey){ + try + { + $telemetryKey = $InstrumentationKey + # Read CSV file here + $EventName = "OrgDetails_Event" + $FilePath = $OrgMappingFilePath + + if(-not([string]::IsNullOrEmpty($FilePath)) -and (Test-Path -path $FilePath -PathType Leaf)) + { + $OrgMappingDetails = Get-Content $FilePath | ConvertFrom-Csv + }else{ + + Write-Host "Unable to read file, Please check file path and try again." -ForegroundColor Red + return; + } + + + + $OrgMappingDetails | ForEach-Object{ + + PublishEvent -EventName $EventName -Properties @{ + "BGName"=$_.BGName ;` + "ServiceGroupName"=$_.ServiceGroupName ;` + "SubscriptionId"=$_.SubscriptionId ;` + "SubscriptionName"=$_.SubscriptionName ;` + "IsActive" = $_.IsActive;` + "OwnerDetails"=$_.OwnerDetails ; + } + + } + + + } + catch + { + + PublishEvent -EventName "OrgDetails_Event Error" -Properties @{ "ErrorRecord" = ($_ | Out-String) } + } + } + + + +SendOrgDetailsEvent -OrgMappingFilePath "OrgMapping.csv File Path" -InstrumentationKey "< Instrumentation Key >" diff --git a/07-Customizing-AzSK-for-your-Org/TemplateFiles/AzSKComplianceReport.pbit b/07-Customizing-AzSK-for-your-Org/TemplateFiles/AzSKComplianceReport.pbit new file mode 100644 index 00000000..5d2ddc9c Binary files /dev/null and b/07-Customizing-AzSK-for-your-Org/TemplateFiles/AzSKComplianceReport.pbit differ diff --git a/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMapping.csv b/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMapping.csv new file mode 100644 index 00000000..55b16491 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMapping.csv @@ -0,0 +1,2 @@ +BGName,ServiceGroupName,SubscriptionId,SubscriptionName,IsActive,OwnerDetails +BGName1,Sg1,SubId1,SubName1,Y,Owner@Contoso.com;Owner1@Contoso.com diff --git a/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMappingDataSourceSchema.json b/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMappingDataSourceSchema.json new file mode 100644 index 00000000..18a07638 --- /dev/null +++ b/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMappingDataSourceSchema.json @@ -0,0 +1,12 @@ +[ + {"location": "0", "name": "BGName", "type": "string"}, + + {"location": "1", "name": "ServiceGroupName", "type": "string"}, + + {"location": "2", "name": "SubscriptionId", "type": "string"}, + + {"location": "3", "name": "SubscriptionName", "type": "string"}, + + {"location": "4", "name": "OwnerDetails", "type": "string"} + +] \ No newline at end of file diff --git a/08-Advanced-Features/Readme.md b/08-Miscellaneous-Features/Readme.md similarity index 50% rename from 08-Advanced-Features/Readme.md rename to 08-Miscellaneous-Features/Readme.md index 47ca052a..01c82a7c 100644 --- a/08-Advanced-Features/Readme.md +++ b/08-Miscellaneous-Features/Readme.md @@ -1,16 +1,25 @@ -# Advanced features +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# Miscellaneous features ### Contents ### [Fetch information about various AzSK components](Readme.md#fetch-information-about-various-azsk-components) - [Overview](Readme.md#overview) - [Subscription information](Readme.md#subscription-information) - [Control information](Readme.md#control-information) +- [Compliance information](Readme.md#compliance-information) - [Attestation information](Readme.md#attestation-information) - [Host information](Readme.md#host-information) +- [User comments](Readme.md#user-comments) + +### [Try AzSK on Power Shell Core](Readme.md#try-azsk-on-powershell-core) ### Overview -This command provides overall information about the AzSK which includes subscription information (alert/policies/ASC/CA version etc.), security controls information (severity, description, rationale etc.), attestation information (statistics, attestation justification, expiry etc.), host information (AzSK settings/configuration, AzureRM Context etc.). 'Get-AzSKInfo' command can be used with 'InfoType' parameter to fetch information. +This command provides overall information about the AzSK which includes subscription information (alert/policies/ASC/CA version etc.), security controls information (severity, description, rationale etc.), attestation information (statistics, attestation justification, expiry etc.), host information (AzSK settings/configuration, Az Context etc.). 'Get-AzSKInfo' command can be used with 'InfoType' parameter to fetch information. ### Subscription information @@ -47,6 +56,7 @@ Run below command to get information about Azure services security control(s). C [-ResourceTypeName ] ` [-ControlIds ] ` [-UseBaselineControls] ` + [-UsePreviewBaselineControls] ` [-FilterTags ] ` [-ControlSeverity ] ` [-ControlIdContains ] ` @@ -58,7 +68,8 @@ Run below command to get information about Azure services security control(s). C |ResourceTypeName|Friendly name of resource type. Run command 'Get-AzSKSupportedResourceTypes' to get the list of supported values. E.g. AppService, KeyVault|TRUE|All| |ControlIds|Comma-separated list of Control Ids|FALSE|None| |UseBaselineControls|The flag used to get details of controls defined in baseline|FALSE|None| -|FilterTags|Comma-seperated tags to filter the security controls. E.g., RBAC, AuthN, etc.|FALSE|None| +|UsePreviewBaselineControls|The flag used to get details of controls defined in preview baseline|FALSE|None| +|FilterTags|Comma-separated tags to filter the security controls. E.g., RBAC, AuthN, etc.|FALSE|None| |ControlSeverity|Filter by severity of control E.g., Critical, High, Medium, Low|FALSE|None| |ControlIdContains|Filter by ControlId(s) contains keyword|FALSE|None| |Verbose|Get information on PS console|FALSE|None| @@ -67,12 +78,38 @@ Run below command to get information about Azure services security control(s). C Below is the sample output: Output of control details summary + ![08_Info_ControlInfo_Summary_PS](../Images/08_Info_ControlInfo_Summary_PS.PNG) Output of control details verbose ![08_Info_ControlInfo_Verbose_PS](../Images/08_Info_ControlInfo_Verbose_PS.PNG) [Back to top…](Readme.md#contents) +### Compliance information + +If this feature is enabled then last scan results will be stored in user’s subscription after every successful scan by CA/CICD/Ad-hoc scan. This cmdlet will fetch the stored scan results and calculate compliance of the subscription. CSV file is also generated by this cmdlet which contains control level information of each resource in your subscription. This lets subscription owners get the current (latest) view of all controls from a compliance standpoint. + +To get compliance info run below command. + +```PowerShell + Get-AzSKInfo -SubscriptionId -InfoType 'ComplianceInfo' +``` +> Note: It's recommended to scan the complete subscription (commands: Get-AzSKSubscriptionSecurityStatus & Get-AzSKAzureServicesSecurityStatus) with co-administrator/owner access atleast once before running above command. This onetime activity is required to ensure all controls are scanned and results are stored in subscription first time. Afterwords stored scan results will get updated with every CA/CICD/Ad-hoc scan and you can get accurate compliance information. + +Below is the sample output + +* PowerShell console output + +![08_Info_ComplianceInfo_Summary_PS](../Images/08_Info_ComplianceInfo_Summary_PS.PNG) + +* CSV report + +![08_Info_ComplianceInfo_Summary_DetailedCSV](../Images/08_Info_ComplianceInfo_Summary_DetailedCSV.PNG) + + +[Back to top…](Readme.md#contents) + + ### Attestation information Run below command to get information about attested security control(s) in user's subscription i.e. Attestation status, attested by, attestation date, attestation expiry date, justification, attested data. It also provides different attestation statistics which includes distribution of attested controls by actual scan result (Failed/Verify), ControlId, Control severity, Expiry date (next 30 days). @@ -84,7 +121,8 @@ Run below command to get information about attested security control(s) in user' [-ResourceGroupNames ] ` [-ResourceNames ] ` [-ControlIds ] ` - [-UseBaselineControls] + [-UseBaselineControls] ` + [-UsePreviewBaselineControls] ``` |Param Name|Purpose|Required?|Default value| @@ -95,6 +133,7 @@ Run below command to get information about attested security control(s) in user' |ResourceNames|Comma-separated list of the name of the resources|FALSE| | |ControlIds|Comma-separated list of Control Ids|FALSE|None| |UseBaselineControls|The flag used to get attestation details of controls defined in baseline|FALSE|None| +|UsePreviewBaselineControls|The flag used to get attestation details of controls defined in baseline|FALSE|None| Below is the sample output: @@ -118,7 +157,7 @@ Run below command to get information about, * Logged in user's details * AzSK settings * AzSK configurations -* AzureRM context +* Az context ```PowerShell Get-AzSKInfo -InfoType 'HostInfo' @@ -127,3 +166,54 @@ Run below command to get information about, Below is the sample output: ![08_Info_HostInfo_PS](../Images/08_Info_HostInfo_PS.PNG) +[Back to top…](Readme.md#contents) + +### User comments + +To track compliance progress on your subscription you can place 'custom tags/comments' on controls, these comments will be persisted inside your subscription's AzSK storage account. Anyone across your subscription can read the comments later by running GSS/GRS/GCS command with switch "-IncludeUserComments". + + +#### How to add/update user comments? + +Please follow the following steps to update user comments: + +Step 1: Run GRS/GSS/GCS cmd with “-IncludeUserComments” switch. For e.g. +```PowerShell + Get-AzSKAzureServicesSecurityStatus -SubscriptionId -IncludeUserComments +``` + +In the .CSV file that is generated, there will be an extra column “UserComments” which will contain custom comments provided by users. + +Step 2: Edit/Update “UserComments” column and save file. + +Step 3: Upload edited .CSV file using below cmdlt, +```PowerShell + Update-AzSKPersistedState -SubscriptionId  -FilePath -StateType "UserComments" +``` +#### How to read user comments? + +To read user comments on any controls you just need to run GCS/GSS/GRS cmd with an extra switch "-IncludeUserComments". Once a scan completes the .CSV file will contain "UserComments" column which will show comments/custom tags. + +![08_Info_UserComments_PS](../Images/08_Info_UserComments_PS.JPG) +[Back to top…](Readme.md#contents) + +### Try AzSK on PowerShell Core + +Follow these steps to try out AzSK in Power Shell Core + +1. Install PowerShell core in your machine using the this [link](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6). +2. Open PowerShell console (e.g. In Linux, run pwsh to open). +3. Install AzSK module using the below command +```PowerShell + Install-Module AzSK +``` +Note: This will download all the dependencies of AzSK along with the AzSK module. However, we will overwrite with the PSCore-ready AzSK module in the next step. + +4. Import the module to your power shell session by running: +```PowerShell + Import-Module AzSK +``` +5. Once the module is imported you can list the commands by running the following: +```PowerShell + Get-Command -Module AzSK +``` diff --git a/09-AzureDevOps(VSTS)-Security/Readme.md b/09-AzureDevOps(VSTS)-Security/Readme.md new file mode 100644 index 00000000..4ed2bc10 --- /dev/null +++ b/09-AzureDevOps(VSTS)-Security/Readme.md @@ -0,0 +1,4 @@ +# Azure DevOps (ADO) Security Scanner + +Documentation for ADO Security Scanner have been moved to a new location. Please follow this [link](https://github.com/azsk/ADOScanner-docs) to access the docs. + diff --git a/10-Continuous-Assurance-for-in-Cluster/Readme.md b/10-Continuous-Assurance-for-in-Cluster/Readme.md new file mode 100644 index 00000000..20d0b057 --- /dev/null +++ b/10-Continuous-Assurance-for-in-Cluster/Readme.md @@ -0,0 +1,179 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +# AzSK Continuous Assurance for Cluster Installation Steps + +### Contents + +- [Prerequisites](Readme.md#prerequisites) +- [Setting up HDInsight](Readme.md#Setting-up-HDInsight) +- [Setting up Azure Databricks](Readme.md#Setting-up-Azure-Databricks) +- [Setting up AKS](Readme.md#Setting-up-AKS) +----------------------------------------------------------------- + +## Prerequisites +1. For every cluster type, we assume the required cluster is already created in your subscription. +2. You may need to pass additional details like cluster location (for Databricks) so note it down while creating the resource to keep it handy. +3. All scripts use Azure Powershell. If you don’t have it installed please visit: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?view=azure-cli-latest +4. For Kubernetes, additionally you will need to install `kubectl`. Run the following command after installing Azure PowerShell + ```PowerShell + az aks install-cli + ``` + +## Setting up HDInsight + +1. Install Continuous Assurance for HDInsight cluster using the command: + + ![HDI-Step1](../Images/HDI-Step1.png) + +2. On successful installation you will see the following results. You may pass the *-Force* parameter to reinstall `AzSKPy` to force reinstallation to a new version. + + ![HDI-Step2](../Images/HDI-Step2.png) + +3. This will add a new notebook to your `PySpark` folder in the HDI Cluster. + + ![HDI-Step3](../Images/HDI-Step3.png) + +4. Open the notebook. + +5. Hit *Shift+Enter* or select *Cell -> Run* all to run all the cells and see the output. + + ![HDI-Step5](../Images/HDI-Step5.png) + +6. The next cell will display recommendations. + + ![HDI-Step6](../Images/HDI-Step6.png) + +## Get Status for HDInsight + +1. You can check the health of the CA using the following command: + ``` + Get-AzSKContinuousAssuranceForCluster -ResourceType HDInsight + ``` + +2. This command will give you the information about on CA health like last scan run, and other metadata. + +## Update CA for HDInsight + +1. Updating CA for HDInsight will update the content for notebook. You can also update the Application Insights key using the command. + ``` + Update-AzSKContinuousAssuranceForCluster -ResourceType HDInsight + ``` +## Removing CA for HDInsight + +1. To uninstall CA, use the following command. This will *preserve* the scan logs of previous scans. You can access them by going into the /AzSK_Logs/ directory on the storage account. + ``` + Remove-AzSKContinuousAssuranceForCluster -ResourceType HDInsight + ``` + +## Setting up Azure Databricks + +1. Use the following command to setup AzSK job for Databricks and input the cluster location and PAT. + + ![ADB-Step1](../Images/ADB-Step1.png) + +2. Go to your cluster settings in workspace and make sure it's running. In the Libraries tab, select intsall new. Then select library source as "PyPi". Leave the Repository blank and enter "azskpy" in the Package text field and click install. This will install the AzSKPy library in the cluster. + +3. Head on to your Databricks Workspace to open up the notebook. + + ![ADB-Step2](../Images/ADB-Step2.png) + +4. Similarly, press *Shift+Enter* to run the cells, or *Run All* to show the output. + + ![ADB-Step3](../Images/ADB-Step3.png) + +5. The next cell will show the recommendations to fix the controls. + + ![ADB-Step4](../Images/ADB-Step4.png) + +## Get Status for Databricks + +1. You can check the health of the CA for Databricks using the following command: + ``` + Get-AzSKContinuousAssuranceForCluster -ResourceType Databricks + ``` + +2. This command will give you the information about on CA health like whether all the required scan permission are present. + +## Update CA for Databricks + +1. Updating CA for Databricks will update the content for notebook. You can also update other data like PAT, Application Insights key using the command. + ``` + Update-AzSKContinuousAssuranceForCluster -ResourceType Databricks + ``` +## Removing CA for Databricks + +1. To uninstall CA, use the following command. This will *preserve* the scan logs of previous scans. You can access them by going into the /AzSK_Logs/ directory in the workspace storage. + ``` + Remove-AzSKContinuousAssuranceForCluster -ResourceType Databricks + ``` + +## Setting up AKS + +1. To install AzSK CA on Kubernetes cluster run the below command + + ```PowerShell + Install-AzSKContinuousAssuranceForCluster -SubscriptionId -ResourceGroupName -ResourceName -ResourceType Kubernetes [ -LAWorkspaceId -LASharedSecret ] + ``` + + ![AKS-Step1](../Images/AKS-Step1.png) + + During insatallation you can also provide workspace ID and shared key of Log Analytics workspace, If you want to send security scan results to Log Analytics for monitoring. + +2. To view the logs of the last CA job, run the below command + + ```PowerShell + $lastJobPod = kubectl get pods --namespace azsk-scanner -o jsonpath='{.items[-1:].metadata.name}' + Kubectl logs $lastJobPod --namespace azsk-scanner + ``` + ![AKS-Step2](../Images/AKS-Step2.png) + +3. To view details like CA job schedule, last schedule run the below command + + + ```PowerShell + kubectl get cronjob azsk-ca-job --namespace azsk-scanner + ``` + ![AKS-Step3](../Images/AKS-Step3.png) + +4. To view logs of any specific job + + a. List all the pods created by AzSK CA job using below command + + ```PowerShell + kubectl get pods --namespace azsk-scanner + ``` + + ![AKS-Step4a](../Images/AKS-Step4a.png) + + b. Pick up the pod name for which you want to see the logs, and run the below after replacing the podname + + ```PowerShell + Kubectl logs --namespace azsk-scanner + ``` + + ![AKS-Step4b](../Images/AKS-Step4b.PNG) + +## Get Status for AKS + +1. You can check the health of the CA for Kubernetes using the following command: + +```PowerShell + Get-AzSKContinuousAssuranceForCluster -SubscriptionId -ResourceGroupName -ResourceName -ResourceType Kubernetes +``` + +2. This command will give you the information about on CA health like whether all the required scan permission are present. + +## Update CA for AKS + +1. Updating CA for Kubernetes will update the image used for scanning cluster. You can also update other configuration like scan interval, Application Insights key or can fix runtime account permissions key using the command. +```PowerShell + Update-AzSKContinuousAssuranceForCluster -SubscriptionId -ResourceGroupName -ResourceName -ResourceType Kubernetes [ -NewAppInsightKey ] [ -NewLAWorkspaceId ] [ -NewLASharedSecret ] [ -FixRuntimeAccount ] [ -LogRetentionInDays ] [ -SpecificImageVersion ] [-ScanIntervalInHours ] +``` +## Removing CA for AKS + +1. To uninstall CA, use the following command. This will download the scan logs of previous scans to your local machine. You can also choose not to download previous scan logs. + +```PowerShell + Remove-AzSKContinuousAssuranceForCluster SubscriptionId -ResourceGroupName -ResourceName -ResourceType Kubernetes [-DownloadJobLogs ] +``` diff --git a/11-Azure Active Directory (AAD) Security Checks/README.md b/11-Azure Active Directory (AAD) Security Checks/README.md new file mode 100644 index 00000000..d163d5bd --- /dev/null +++ b/11-Azure Active Directory (AAD) Security Checks/README.md @@ -0,0 +1,70 @@ +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. +# (Preview) Security Scan of Azure Active Directory (AAD) + +A new module called AzSK.AAD is available in preview to facilitate checking security configuration and best practices for Azure Active Directory (AAD). It provides the ability to scan the entire tenant (a feature that AAD admins can use) or scan objects of various types (apps, groups, devices, etc.) owned by a specific user (a feature that an individual user in the tenant can use). + + +## Installation + +> **Pre-requisites**: +> - PowerShell 5.0 or higher. +> - .Net Framework 4.7.2 or higher. + +1. Verify that prerequisites are installed: + Ensure that you have PowerShell version 5.0 or higher by typing **$PSVersionTable** in the PowerShell ISE console window and looking at the PSVersion in the output as shown below.) + If the PSVersion is older than 5.0, update PowerShell from [here](https://www.microsoft.com/en-us/download/details.aspx?id=54616). + ![PowerShell Version](../Images/00_PS_Version.PNG) + +2. Install the AzSK.AAD PowerShell module: + +```PowerShell + Install-Module AzSK.AAD -Scope CurrentUser +``` + +Note: + + - You may need to use `-AllowClobber` and/or `-Force` options with the `Install-Module` command above if you already have a prior version of the module installed on your machine. + - The `AzSK.AAD` module depends on `AzureAD` and `Az.Accounts` modules. + - The Az.Accounts module requires .Net Framework 4.7.2. If your machine does not have .Net Framework 4.7.2, you may need to independently install it. + + +## Scan your AAD resources + +Use the commands below based on if you wish to scan the entire tenant or as an end user. Even if you do not have admin permissions to the tenant, you can _still_ use the tenant version of the command. In such a case, the command will scan the controls that it can based on your permissions. + +When using the 'tenant' cmdlet, all tenant-level controls are always scanned. Apart from those, a desired number of objects of chosen types (or 'all' types) are also scanned. + +When using the 'user' cmdlet, tenant controls are not scanned and only objects of chosen (or all) types that are owned by the current user are scanned for security issues and best practices. + +At present (for this preview release), 'MaxObj' defaults to 3 if not specified. You may be choose a higher value if you are scanning the entire tenant. Also, the default value of 'ObjectType' is 'All'. + +### Scanning tenant-wide: +```PowerShell +Get-AzSKAADSecurityStatusTenant + +Get-AzSKAADSecurityStatusTenant -TenantId + +Get-AzSKAADSecurityStatusTenant -TenantId -ObjectType [User|Application|ServicePrincipal|Group|Device|All] -MaxObj 2 +``` + +### Scanning at a 'user' scope: +```PowerShell +Get-AzSKAADSecurityStatusUser + +Get-AzSKAADSecurityStatusUser -TenantId + +Get-AzSKSecurityStatusUser -TenantId -ObjectType [User|Application|ServicePrincipal|Group|Device|All] -MaxObj 2 +``` + +Note: You can get your AAD tenantId by running the following in PS after installing the `AzSK.AAD` module:
    `$tenantId = (Get-AzureADTenantDetail).ObjectId` + +Similar to the Azure AzSK scan commands, outcome of the analysis is printed on the console during SVT execution and a CSV and LOG files are +also generated for subsequent use. + +The CSV file and LOG file are generated under a Org-specific sub-folder in the folder +*%LOCALAPPDATA%\Microsoft\AzSK.AADLogs\Org_[yourOrganizationName]* +E.g. +C:\Users\UserName\AppData\Local\Microsoft\AzSK.AADLogs\Org_[yourOrganizationName]\20181218_103136_GADS + +Refer [doc](../02-Secure-Development#understand-the-scan-reports) for understanding the scan report and [link](./ControlCoverage) for current control coverage for AAD. (#TODO) diff --git a/12-AzSK setup to scan subscriptions across tenants/CrossTenantParams.json b/12-AzSK setup to scan subscriptions across tenants/CrossTenantParams.json new file mode 100644 index 00000000..1c0a45e5 --- /dev/null +++ b/12-AzSK setup to scan subscriptions across tenants/CrossTenantParams.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "mspOfferName": { + "value": "AzSK Access from the central tenant" + }, + "mspOfferDescription": { + "value": "Cross-tenant Delegation for AzSK CA" + }, + "managedByTenantId": { + "value": "" + }, + "authorizations": { + "value": [ + { + "principalId": "", + "principalIdDisplayName": "", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + } + ] + } + } +} diff --git a/12-AzSK setup to scan subscriptions across tenants/README.md b/12-AzSK setup to scan subscriptions across tenants/README.md new file mode 100644 index 00000000..fcdcd8da --- /dev/null +++ b/12-AzSK setup to scan subscriptions across tenants/README.md @@ -0,0 +1,79 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + +# AzSK setup across multiple tenants + +There are scenarios where teams have multiple Azure subscriptions spread across multiple tenants. Typically they can deploy one 'Continuous Assurance' setup per tenant (in central scan mode) and push the AzSK scan results from all of them into a single central Log Analytics workspace. + +The above solution can be simplified using the following steps, albeit with some limitations listed in the end. + +## How to setup cross tenant Continuous Assurance (CA)? + +By now you would be aware that when you install CA in your Azure subscription, it adds a service principal runtime account as a 'reader' on that subscription. So when you want to setup CA on subscriptions that are spread across multiple tenants, it would be required that this service principal runtime account has 'reader' access on all those subscriptions. + +You can achieve it by using Azure delegated resource management. +Azure delegated resource management enables logical projection of resources from one tenant onto another tenant. + +>NOTE: This approach has certain [known limitations](README.md#known-limitations). It would be important that you go through them before you take all the steps listed below. + +### Prerequisites: +1. You need to have 'Owner' permissions on all the subscriptions i.e. on which you want to setup CA and the ones which you want to be scanned by CA. +2. You need to know the tenant id of the subscription where the CA automation account and other related components will be installed. We will refer this subscription as 'central subscription' in the context of this article. +3. You need to know the subscription ids of the target subscriptions. + +### Steps to follow: +1. Go to your central subscription. +2. Go to 'App registrations' and click on '+New registration'. +3. Select type 'Accounts in any organizational directory (Any Azure AD directory - Multitenant)'. + ![App Registration](../Images/12_AppRegistration.png) +4. Provide 'Name' and click on 'Register'. +5. Once the app registration is completed, click on 'Managed application in local directory' under 'Overview'. +6. It will open up 'Properties' blade of the enterprise application. Note the 'ObjectId' of the application. It would be required in the further steps. + ![Object Id](../Images/12_AppObjectId.png) +7. Update the [CrossTenantParams.json](./CrossTenantParams.json) with the collected prerequisites. +8. Deploy the [delegatedResourceManagement.json](./delegatedResourceManagement.json) and [CrossTenantParams.json](./CrossTenantParams.json) to the target subscription using the commands below: + + ```PowerShell + # Log in first with Connect-AzAccount + Connect-AzAccount + + # Set context to the target subscription + Set-AzContext -Subscription + + # Deploy Azure Resource Manager template using template and parameter file locally + New-AzDeployment -Name ` + -Location ` + -TemplateFile ` + -TemplateParameterFile ` + -Verbose + + ``` +9. You can confirm successful onboarding of the target subscription by going to 'Service Providers' page in target subscription. +10. You need to follow this process for all the target subs that you want to onboard to CA. +11. Now you need to install CA on the central subscription using the command below: + + ```PowerShell + Install-AzSKContinuousAssurance -SubscriptionId ` + -AzureADAppName ` + -TargetSubscriptionIds $TargetSubscriptionIds ` + -ResourceGroupNames $ResourceGroupNames ` + -LAWSId $LAWSId -LAWSSharedKey $LAWSSharedKey ` + -CentralScanMode ` + -LoggingOption 'CentralSub' ` + -SkipTargetSubscriptionConfig + ``` + +12. Note that CA scan logs for all the target subscriptions will be available in the storage under AzSKRG resource group of the central subscription. + + +## Known limitations +* Currently, you can’t onboard a subscription (or resource group within a subscription) for Azure delegated resource management if the subscription uses Azure Databricks. Similarly, if a subscription has been registered for onboarding with the Microsoft.ManagedServices resource provider, you won’t be able to create a Databricks workspace for that subscription at this time. + +* While you can onboard subscriptions and resource groups for Azure delegated resource management which have resource locks, those locks will not prevent actions from being performed by users in the managing tenant. Deny assignments that protect system-managed resources, such as those created by Azure managed applications or Azure Blueprints (system-assigned deny assignments), do prevent users in the managing tenant from acting on those resources; however, at this time users in the customer tenant can’t create their own deny assignments (user-assigned deny assignments). + + +## References +1. [Azure delegated resource management](https://docs.microsoft.com/en-us/azure/lighthouse/concepts/azure-delegated-resource-management) diff --git a/12-AzSK setup to scan subscriptions across tenants/delegatedResourceManagement.json b/12-AzSK setup to scan subscriptions across tenants/delegatedResourceManagement.json new file mode 100644 index 00000000..4fbed3dd --- /dev/null +++ b/12-AzSK setup to scan subscriptions across tenants/delegatedResourceManagement.json @@ -0,0 +1,135 @@ +{ + + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + + "contentVersion": "1.0.0.0", + + "parameters": { + + "mspOfferName": { + + "type": "string", + + "metadata": { + + "description": "Specify the name of the offer from the Managed Service Provider" + + } + + }, + + "mspOfferDescription": { + + "type": "string", + + "metadata": { + + "description": "Name of the Managed Service Provider offering" + + } + + }, + + "managedByTenantId": { + + "type": "string", + + "metadata": { + + "description": "Specify the tenant id of the Managed Service Provider" + + } + + }, + + "authorizations": { + + "type": "array", + + "metadata": { + + "description": "Specify an array of objects, containing tuples of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider's Active Directory and the principalIdDisplayName is visible to customers." + + } + + } + + }, + + "variables": { + + "mspRegistrationName": "[guid(parameters('mspOfferName'))]", + + "mspAssignmentName": "[guid(parameters('mspOfferName'))]" + + }, + + "resources": [ + + { + + "type": "Microsoft.ManagedServices/registrationDefinitions", + + "apiVersion": "2019-06-01", + + "name": "[variables('mspRegistrationName')]", + + "properties": { + + "registrationDefinitionName": "[parameters('mspOfferName')]", + + "description": "[parameters('mspOfferDescription')]", + + "managedByTenantId": "[parameters('managedByTenantId')]", + + "authorizations": "[parameters('authorizations')]" + + } + + }, + + { + + "type": "Microsoft.ManagedServices/registrationAssignments", + + "apiVersion": "2019-06-01", + + "name": "[variables('mspAssignmentName')]", + + "dependsOn": [ + + "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]" + + ], + + "properties": { + + "registrationDefinitionId": "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]" + + } + + } + + ], + + "outputs": { + + "mspOfferName": { + + "type": "string", + + "value": "[concat('Managed by', ' ', parameters('mspOfferName'))]" + + }, + + "authorizations": { + + "type": "array", + + "value": "[parameters('authorizations')]" + + } + + } + +} \ No newline at end of file diff --git a/13-Tenant Security Solution Setup/Readme.md b/13-Tenant Security Solution Setup/Readme.md new file mode 100644 index 00000000..88353256 --- /dev/null +++ b/13-Tenant Security Solution Setup/Readme.md @@ -0,0 +1,3 @@ +# Azure Tenant Security Solution (AzTS) + +Documentation for Azure Tenant Security Solution (AzTS) have been moved to a new location. Please follow this [link](https://github.com/azsk/AzTS-docs) to access the docs. diff --git a/14-Transition-and-Cleanup/Readme.md b/14-Transition-and-Cleanup/Readme.md new file mode 100644 index 00000000..ec783e2e --- /dev/null +++ b/14-Transition-and-Cleanup/Readme.md @@ -0,0 +1,63 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. + +# Transition and Cleanup + +## Cleanup + ### Contents +- [Remove AzSK deployed resources](Readme.md#remove-azsk-deployed-resources) +- [FAQ](Readme.md#faq) +----------------------------------------------------------------- +## Remove AzSK deployed resources +"Secure DevOps Kit for Azure (AzSK)" is on the path of sunset, and being transitioned to more robust & scalable solution called Azure Tenant Security scanner (AzTS). If transition from AzSK to AzTS is done for your organization and tenant, you can follow below mentioned steps to clean up AzSK deployed resources in your subscription. + +>**Note** Before running command to clean-up AzSK deployed resources, please do have a look on the section below (post the steps to clean resources) which lists all the resources which will be deleted as part of clean-up and points to consider before deletion. + +### Steps to clean AzSK deployed resources: + +**Step 1:** Import AzSK module: + +``` PowerShell + Import-Module AzSK +``` +**Step 2:** Run Remove-AzSKContinuousAssurance command with '-CleanUpAllAzSKResources' switch: + +``` PowerShell +Remove-AzSKContinuousAssurance -SubscriptionId "" -CleanUpAllAzSKResources +``` +### What all resources will be deleted? + +The above command will delete following resources under resource group 'AzSKRG' and resource group 'AzSKRG': + +|Type|Name|Points to consider?| +|----|----|----| +|Microsoft.Storage/storageAccounts|azsk*|Avoid deleting, if:
    a) You want to keep previous AzSK CA scan logs
    b) You want to keep attestation of non-baseline controls
    c) You are using AzSK Cred Hygiene feature| +|Microsoft.Automation/automationAccounts/runbooks|Continuous_Assurance_Runbook, Alert_Runbook, Continuous_Assurance_ScanOnTrigger_Runbook|NA| +|Microsoft.Automation/automationAccounts|AzSKContinuousAssurance|Avoid deleting, if You have deployed any custom runbook in AzSK Automation account. | +|Microsoft.Insights/activityLogAlerts|AzSK_*|Avoid deleting, if dependent on AzSK alerts for alerting & monitoring.| +|Microsoft.Insights/actionGroups|AzSKAlertActionGroup, AzSKCriticalAlertActionGroup, ResourceDeploymentActionGroup|Avoid deleting, if used same action groups for any non-AzSK deployed alerts.| + +Apart from deleting above mentioned resources, command will also remove: +- Role assignments of current SPN (service principal) associated with AzSK Automation account. + - 'Reader' role at subscrition scope and + - 'Contributor' at 'AzSKRG' resource group scope +- Azure AD Application (AzSK_CA_SPN_*) and SPN associated with AzSK Automation account. + +>**Note 1:** To clean AAD application you must have "Owner" access to the AAD application and ability to remove AAD application in the tenant. + +>**Note 2:** During AzSK CA set up separate AAD application & SPN gets created. So, it is safe to delete AAD application & SPN associated with the automation account. But if you had manually added same SPN/AAD application to some other application or AzSK CAs then please avoid deleting AAD application. + +### FAQ + +#### Can I run the command in non interactive manner, so that I don't need to provide any further input/confirmation? +Yes, you can run the command in non interactive mode to perform the clean up without any prompt for confirmation/input. For this please include '-Force' switch while running the command as shown in example below. + +``` PowerShell +Remove-AzSKContinuousAssurance -SubscriptionId "" -CleanUpAllAzSKResources -Force +``` +Please be careful while using '-Force' switch as this will delete all AzSK deployed resources (including AzSK CA SPN & AAD App) without any further consent from the user. + + diff --git a/14-Transition-and-Cleanup/scripts/DeleteAzSKRG.ps1 b/14-Transition-and-Cleanup/scripts/DeleteAzSKRG.ps1 new file mode 100644 index 00000000..295fac96 --- /dev/null +++ b/14-Transition-and-Cleanup/scripts/DeleteAzSKRG.ps1 @@ -0,0 +1,454 @@ + +function Pre_requisites { + <# + .SYNOPSIS + This function would check pre requisities modules. + .DESCRIPTION + This function would check pre requisities modules to perform clean-up. + #> + + Write-Host "Required modules are: Az.Resources, Az.Accounts" -ForegroundColor Cyan + Write-Host "Checking for required modules..." + $availableModules = $(Get-Module -ListAvailable Az.Resources, Az.Accounts) + + # Checking if 'Az.Accounts' module is available or not. + if ($availableModules.Name -notcontains 'Az.Accounts') { + Write-Host "Installing module Az.Accounts..." -ForegroundColor Yellow + Install-Module -Name Az.Accounts -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Accounts module is available." -ForegroundColor Green + } + + # Checking if 'Az.Resources' module is available or not. + if ($availableModules.Name -notcontains 'Az.Resources') { + Write-Host "Installing module Az.Resources..." -ForegroundColor Yellow + Install-Module -Name Az.Resources -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Resources module is available." -ForegroundColor Green + } +} + +function Read_UserChoice { + #This function would read user input and return trimmed value + $userSelection = "" + while ($userSelection -ne 'Y' -and $userSelection -ne 'N') { + $userSelection = Read-Host "User choice" + if (-not [string]::IsNullOrWhiteSpace($userSelection)) { + $userSelection = $userSelection.Trim(); + } + } + return $userSelection; +} + + +function Remove-AzSKResourceGroups { + <# + .SYNOPSIS + This command would help in deleting the AzSK deployed Azure resources in subscription. + .DESCRIPTION + This command will list all resources deployed in AzSKRG nd AzSDKRG and divide them in two list a). AzSK deployed resources b). Non-AzSK deployed resources and will provide option to delete RG + .PARAMETER SubscriptionId + Enter subscription id of the subscription for which clean-up need to be performed. + .PARAMETER PerformPreReqCheck + Perform pre requisities check to ensure all required module to perform clean-up operation is available. + .PARAMETER Force + Switch to force deletion of AzSK resources without further user consent. + #> + param ( + [string] + [Parameter(Mandatory = $true, HelpMessage = "Enter subscription id to delete resource groups for AzSK related resources: ")] + $SubscriptionId, + [Parameter(Mandatory = $false, HelpMessage = "Use this switch to avoid user confimration before deletion of resource groups")] + [switch] + $Force + ) + + Write-Host "======================================================" + + try { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host "------------------------------------------------------" + } + catch { + Write-Host "Error occured while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + + + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + + # Setting context for current subscription. + $currentSub = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop -Force + + Write-Host "Metadata Details: `n SubscriptionId: [$($SubscriptionId)] `n AccountName: [$($currentSub.Account.Id)] `n AccountType: [$($currentSub.Account.Type)]" + Write-Host "------------------------------------------------------" + Write-Host "Starting with Subscription [$($SubscriptionId)]..." + + + Write-Host "`nStep 1: Validating whether the current user [$($currentSub.Account.Id)] have the required permissions to run the script for Subscription [$($SubscriptionId)]..." + + # Safe Check: Checking whether the current account is of type User + if ($currentSub.Account.Type -ne "User") { + Write-Host "WARNING: This script can only be run by user account type." -ForegroundColor Yellow + break; + } + + # Safe Check: Current user need to have Owner role for the subscription + $currentLoginRoleAssignments = Get-AzRoleAssignment -SignInName $currentSub.Account.Id -Scope "/subscriptions/$($SubscriptionId)" -IncludeClassicAdministrators; + + if (($currentLoginRoleAssignments | Where-Object { $_.RoleDefinitionName -eq "Owner" -or $_.RoleDefinitionName -match 'CoAdministrator' -or $_.RoleDefinitionName -like '*ServiceAdministrator*' } | Measure-Object).Count -le 0) { + Write-Host "WARNING: This script can only be run by an Owner of subscription [$($SubscriptionId)] " -ForegroundColor Yellow + break; + } + else { + Write-Host "User has all required permissions." -ForegroundColor Green + } + + # Declaring all AzSK resources name/pattern + $azskRGName = "AzSKRG" + $azsdkRGName = "AzSDKRG" + + Write-Host "`nStep 2: Listing AzSK related resource groups in Subscription [$($SubscriptionId)]..." + + # Get AzSK RG + $azskRG = Get-AzResourceGroup $azskRGName -ErrorAction SilentlyContinue + + if (-not $azskRG) { + Write-Host "$($azskRGName) is not present in subscription [$($SubscriptionId)]" -ForegroundColor Green + } + # Get AzSDK RG + $azsdkRG = Get-AzResourceGroup $azsdkRGName -ErrorAction SilentlyContinue + + if (-not $azsdkRG) { + Write-Host "$($azsdkRGName) is not present in subscription [$($SubscriptionId)]" -ForegroundColor Green + + } + #No resource groups found to be cleaned up + if (-not $azsdkRG -and -not $azskRG) { + Write-Host "No resource groups found to be deleted." -ForegroundColor Red + return + } + if ($azskRG) { + RemoveAzSKRG + } + if ($azsdkRG) { + RemoveAzSDKRG + } + #End block +} + +Function RemoveAzSKRG { + # declare all required variables + + $azskRGName = "AzSKRG" + $automationAccountName = "AzSKContinuousAssurance" + $azskRunbookNames = @('AzSKContinuousAssurance/Continuous_Assurance_Runbook', 'AzSKContinuousAssurance/Alert_Runbook', 'AzSKContinuousAssurance/Continuous_Assurance_ScanOnTrigger_Runbook') + $StorageAccountNamePattern = "^azsk\d{14}$" + $alertNamePattern = "AzSK_*_Alert*" + $azskActionGroupNames = @("AzSKAlertActionGroup", "AzSKCriticalAlertActionGroup", "ResourceDeploymentActionGroup") + + $allResources = @() + $azskResources = @() + $nonAzSKResources = @() + $azskRGDeleted = $false + + # Get all resources in AzSKRG + $allResources += Get-AzResource -ResourceGroupName $azskRGName -ErrorAction Stop + + if (($allResources | Measure-Object).Count -gt 0) { + # Check AzSK Stoarge account + $storageAccount = $allResources | Where-Object { $_.Name -match $StorageAccountNamePattern -and $_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if (($storageAccount | Measure-Object).Count -gt 0) { + $azskResources += $storageAccount + } + + # Check AzSK continuous assurance automation accounts + $existingAutomationAccount = $allResources | Where-Object { $_.Name -eq $automationAccountName -and $_.ResourceType -eq "Microsoft.Automation/automationAccounts" } + if (($existingAutomationAccount | Measure-Object).Count -gt 0) { + $azskResources += $existingAutomationAccount + + # Check AzSK runbooks + $existingAzSKRunbooks += $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Automation/automationAccounts/runbooks" -and $_.Name -in $azskRunbookNames } + if (($existingAzSKRunbooks | Measure-Object).Count -gt 0) { + $azskResources += $existingAzSKRunbooks + } + + } + + # Get the alerts + $configuredAlerts = $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Insights/activityLogAlerts" -and $_.Name -like $alertNamePattern } + if ($configuredAlerts) { + $azskResources += $configuredAlerts + } + + # Get the Action Group + $actionGrps = $allResources | Where-Object { $_.ResourceType -eq "microsoft.insights/actiongroups" -and $_.Name -in $azskActionGroupNames } + if ($actionGrps) { + $azskResources += $actionGrps + } + + if ($azskResources) { + $nonAzSKResources += $allResources | Where-Object { $_.Id -inotin $azskResources.Id } + } + else { + $nonAzSKResources += $allResources + } + + + Write-Host "A) Listing AzSK resources present in $($azskRGName):" + if ($azskResources) { + $azskResources | Select-Object Name, ResourceType | Format-Table + } + else { + Write-Host "No such resources found.`n" + } + + Write-Host("B) Listing Non-AzSK resources present in $($azskRGName):") + if ($nonAzSKResources) { + $nonAzSKResources | Select-Object Name, ResourceType | Format-Table + } + else { + Write-Host "No such resources found." + } + + #Display Warning in case NonAzSK resources are present + + if ($nonAzSKResources) { + Write-Host "WARNING: Following Non-AzSK deployed resources are also present in AzSKRG resource group, if you choose to delete resource group, these resources will also be deleted." -ForegroundColor Yellow + $nonAzSKResources | Select-Object Name, ResourceType | Format-Table + Write-Host "`nPlease confirm deletion of all above listed resources: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $userChoice = "" + $userChoice = Read_UserChoice + if ($userChoice -ne 'Y') { + Write-Host "Skipped deletion of $($azskRGName) group." -ForegroundColor Yellow + return + } + } + Write-Host "------------------------------------------------------" + + Write-Host "`nStep 3:Cleaning resources present under resource group [$($azskRGName)] in Subscription [$($SubscriptionId)]..." + + if ($azskResources) { + $userChoice = "" + if ($force) { + $userChoice = "Y" + Write-Host "`nForce parameter is set to 'True', no further consent required." -ForegroundColor Yellow + } + else { + + Write-Host "Please select an action from below: `n[Y]: Delete $($azskRGName) reosurce group `n[N]: Skip deletion for $($azskRGName) resource group`n" -ForegroundColor Cyan + + $userChoice = Read-Host "User choice" + if (-not [string]::IsNullOrWhiteSpace($userChoice)) { + $userChoice = $userChoice.Trim(); + } + + } + switch ($userChoice.ToUpper()) { + "Y" { + #DeleteRG + Write-Host "======================================================" + Write-Host "`n$($azskRGName) resource group and all resources in it will be deleted:" + + Write-Host "------------------------------------------------------" + try { + Write-Host "Deleting AzSK resource group [$($azskRGName)] from subscription [$($SubscriptionId)].This might take few minutes.." + $success = Remove-AzResourceGroup -Name $azskRGName -Force + if (-not $success) { + throw; + } + $azskRGDeleted = $true + + } + catch { + Write-Host "ERROR: Error occurred while deleting resource group [$($azskRGName)], please contact support team." -ForegroundColor Red + } + } + Default { + Write-Host "WARNING: Deletion of AzSK resource group [$($azskRGName)] skipped." -ForegroundColor Yellow + } + } + + # Next Steps + $success = $true + if (-not $azskRGDeleted) { + Write-Host "[$($azskRGName)] is not removed from subscription [$($SubscriptionId)], please look at the wanrings/errors listed above after step #3." + Write-Host "`ta) If there is any Non-AzSK resources present in $($azskRGName), please remove/delete those resources using Azure portal." + Write-Host "`tb) If there is any error occurred while deleting AzSK resources, please look at the error details to resolve or try deleting such resources from Azure portal." + $success = $success -and $false + } + + if ($success) { + Write-Host "------------------------------------------------------" + Write-Host "$($azskRGName) resource group deleted successfully." -ForegroundColor Green + } + + Write-Host "======================================================" -ForegroundColor Cyan + + } + } +} + +Function RemoveAzSDKRG { + # declare all required variables + + $azsdkRGName = "AzSDKRG" + $azsdkRGName = "AzSDKRG" + $automationAccountName = "AzSDKContinuousAssurance" + $azsdkRunbookNames = @('AzSDKContinuousAssurance/Continuous_Assurance_Runbook', 'AzSDKContinuousAssurance/Alert_Runbook', 'AzSDKContinuousAssurance/Continuous_Assurance_ScanOnTrigger_Runbook') + $StorageAccountNamePattern = "^azsdk\d{14}$" + $alertNamePattern = "AzSDK_*_Alert*" + $azsdkActionGroupNames = @("AzSDKAlertActionGroup", "AzSDKCriticalAlertActionGroup", "ResourceDeploymentActionGroup") + + $allResources = @() + $azsdkResources = @() + $nonAzSDKResources = @() + $azsdkRGDeleted = $false + + # Get All resource in AzSDKRG + $allResources += Get-AzResource -ResourceGroupName $azsdkRGName -ErrorAction Stop + + if (($allResources | Measure-Object).Count -gt 0) { + # Check AzSDK Stoarge account + $storageAccount = $allResources | Where-Object { $_.Name -match $StorageAccountNamePattern -and $_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if (($storageAccount | Measure-Object).Count -gt 0) { + $azsdkResources += $storageAccount + } + + # Check AzSDK continuous assurance automation accounts + $existingAutomationAccount = $allResources | Where-Object { $_.Name -eq $automationAccountName -and $_.ResourceType -eq "Microsoft.Automation/automationAccounts" } + if (($existingAutomationAccount | Measure-Object).Count -gt 0) { + $azsdkResources += $existingAutomationAccount + + # Check AzSDK runbooks + $existingAzSDKRunbooks += $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Automation/automationAccounts/runbooks" -and $_.Name -in $azsdkRunbookNames } + if (($existingAzSDKRunbooks | Measure-Object).Count -gt 0) { + $azsdkResources += $existingAzSDKRunbooks + } + + } + + # Get the alerts + $configuredAlerts = $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Insights/activityLogAlerts" -and $_.Name -like $alertNamePattern } + if ($configuredAlerts) { + $azsdkResources += $configuredAlerts + } + + # Get the Action Group + $actionGrps = $allResources | Where-Object { $_.ResourceType -eq "microsoft.insights/actiongroups" -and $_.Name -in $azsdkActionGroupNames } + if ($actionGrps) { + $azsdkResources += $actionGrps + } + + if ($azsdkResources) { + $nonAzSDKResources += $allResources | Where-Object { $_.Id -inotin $azsdkResources.Id } + } + else { + $nonAzSDKResources += $allResources + } + + + Write-Host "A) Listing AzSDK resources present in $($azsdkRGName):" + if ($azsdkResources) { + $azsdkResources | Select-Object Name, ResourceType | Format-Table + } + else { + Write-Host "No such resources found.`n" + } + + Write-Host("B) Listing Non-AzSDK resources present in $($azsdkRGName):") + if ($nonAzSDKResources) { + $nonAzSDKResources | Select-Object Name, ResourceType | Format-Table + } + else { + Write-Host "No such resources found." + } + + #Display Warning in case NonAzSDK resources are present + + if ($nonAzSDKResources) { + Write-Host "WARNING: Following Non-AzSDK deployed resources are also present in AzSDKRG resource group, if you choose to delete resource group, these resources will also be deleted." -ForegroundColor Yellow + $nonAzSDKResources | Select-Object Name, ResourceType | Format-Table + Write-Host "`nPlease confirm deletion of all above listed resources: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $userChoice = "" + $userChoice = Read_UserChoice + if ($userChoice -ne 'Y') { + Write-Host "Skipped deletion of $($azsdkRGName) group." -ForegroundColor Yellow + return + } + } + Write-Host "------------------------------------------------------" + + Write-Host "`nStep 4: Cleaning resources present under resource group [$($azsdkRGName)] in Subscription [$($SubscriptionId)]..." + + if ($azsdkResources) { + $userChoice = "" + if ($force) { + $userChoice = "Y" + Write-Host "`nForce parameter is set to 'True', no further consent required." -ForegroundColor Yellow + } + else { + + Write-Host "Please select an action from below: `n[Y]: Delete $($azsdkRGName) reosurce group `n[N]: Skip deletion for $($azsdkRGName) resource group`n" -ForegroundColor Cyan + + $userChoice = Read-Host "User choice" + if (-not [string]::IsNullOrWhiteSpace($userChoice)) { + $userChoice = $userChoice.Trim(); + } + + } + switch ($userChoice.ToUpper()) { + "Y" { + #DeleteRG + Write-Host "======================================================" + Write-Host "`n$($azsdkRGName) resource group and all resources in it will be deleted:" + + Write-Host "------------------------------------------------------" + try { + Write-Host "Deleting resource group [$($azsdkRGName)] from subscription [$($SubscriptionId)].This might take few minutes.." + $success = Remove-AzResourceGroup -Name $azsdkRGName -Force + if (-not $success) { + throw; + } + $azsdkRGDeleted = $true + + } + catch { + Write-Host "ERROR: Error occurred while deleting resource group [$($azsdkRGName)], please contact support team." -ForegroundColor Red + } + } + Default { + Write-Host "WARNING: Deletion of resource group [$($azsdkRGName)] skipped." -ForegroundColor Yellow + } + } + + # Next Steps + $success = $true + if (-not $azsdkRGDeleted) { + Write-Host "[$($azsdkRGName)] is not removed from subscription [$($SubscriptionId)], please look at the wanrings/errors listed above after step #3." + Write-Host "`ta) If there is any Non-AzSDK resources present in $($azsdkRGName), please remove/delete those resources using Azure portal." + Write-Host "`tb) If there is any error occurred while deleting AzSDK resources, please look at the error details to resolve or try deleting such resources from Azure portal." + $success = $success -and $false + } + + if ($success) { + Write-Host "------------------------------------------------------" + Write-Host "$($azsdkRGName) resource group deleted successfully." -ForegroundColor Green + } + + Write-Host "======================================================" -ForegroundColor Cyan + + } + } +} + + diff --git a/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNAccess.ps1 b/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNAccess.ps1 new file mode 100644 index 00000000..511a337d --- /dev/null +++ b/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNAccess.ps1 @@ -0,0 +1,156 @@ + +function Pre_requisites { + <# + .SYNOPSIS + This function would check pre requisities modules. + .DESCRIPTION + This function would check pre requisities modules to perform clean-up. + #> + + Write-Host "Required modules are: Az.Resources, Az.Accounts" -ForegroundColor Cyan + Write-Host "Checking for required modules..." + $availableModules = $(Get-Module -ListAvailable Az.Resources, Az.Accounts) + + # Checking if 'Az.Accounts' module is available or not. + if ($availableModules.Name -notcontains 'Az.Accounts') { + Write-Host "Installing module Az.Accounts..." -ForegroundColor Yellow + Install-Module -Name Az.Accounts -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Accounts module is available." -ForegroundColor Green + } + + # Checking if 'Az.Resources' module is available or not. + if ($availableModules.Name -notcontains 'Az.Resources') { + Write-Host "Installing module Az.Resources..." -ForegroundColor Yellow + Install-Module -Name Az.Resources -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Resources module is available." -ForegroundColor Green + } + +} + +function Read_UserChoice { + $userSelection = "" + while ($userSelection -ne 'Y' -and $userSelection -ne 'N') { + $userSelection = Read-Host "User choice" + if (-not [string]::IsNullOrWhiteSpace($userSelection)) { + $userSelection = $userSelection.Trim(); + } + } + return $userSelection; +} + +function Delete_RoleAssignments { + param ($AzskRoleAssignments) + Write-Host "Deleting role assignments for AzSK CA SPNs..." + $azskRoleAssignments | Remove-AzRoleAssignment +} + +function Remove-AzSKSPNAccess { + <# + .SYNOPSIS + This command will remove access for AzSK/AzSDK deployed SPNs in subscription.Please make sure to confirm these SPNs are not used for other purpose prior to running this script. + .DESCRIPTION + This command will removing access for AzSK/AzSDK deployed SPNs in subscription.Please make sure to confirm these SPNs are not used for other purpose prior to running this script. + .PARAMETER SubscriptionId + Enter subscription id of the subscription for which access needs to be removed for AzSK/AzSDK SPNs. + .PARAMETER Force + Use this switch to avoid user confimration before deletion for role assignments. + #> + + param ( + [string] + [Parameter(Mandatory = $true, HelpMessage = "Enter subscription id for which AzSK SPN access to be removed")] + $SubscriptionId, + + [switch] + $force + ) + + Write-Host "======================================================" + Write-Host "If you have access to the subscription using Privileged Identity Management(PIM), please make sure to elevate access before running the script." -ForegroundColor Yellow + Write-Host "------------------------------------------------------" + + try { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host "------------------------------------------------------" + } + catch { + Write-Host "Error occured while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + + + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + + # Setting context for current subscription. + $currentSub = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop -Force + + Write-Host "Metadata Details: `n SubscriptionId: [$($SubscriptionId)] `n AccountName: [$($currentSub.Account.Id)] `n AccountType: [$($currentSub.Account.Type)]" + Write-Host "------------------------------------------------------" + + + Write-Host "`nStep 1 of 3: Validating whether the current user [$($currentSub.Account.Id)] have the required permissions to run the script for Subscription [$($SubscriptionId)]..." + + # Safe Check: Checking whether the current account is of type User + if ($currentSub.Account.Type -ne "User") { + Write-Host "WARNING: This script can only be run by user account type." -ForegroundColor Yellow + break; + } + + # Safe Check: Current user need to have Owner role for the subscription + $currentLoginRoleAssignments = Get-AzRoleAssignment -SignInName $currentSub.Account.Id -Scope "/subscriptions/$($SubscriptionId)" -IncludeClassicAdministrators; + + if (($currentLoginRoleAssignments | Where-Object { $_.RoleDefinitionName -eq "Owner" -or $_.RoleDefinitionName -match 'CoAdministrator' -or $_.RoleDefinitionName -like '*ServiceAdministrator*' } | Measure-Object).Count -le 0) { + Write-Host "WARNING: This script can only be run by an Owner of subscription [$($SubscriptionId)] " -ForegroundColor Yellow + break; + } + else { + Write-Host "User has all required permissions." -ForegroundColor Green + } + + # Declaring all AzSK and AzSDK SPN resources name/pattern + $azskLocalSPNFormatString = "AzSK_CA_SPN_*" + $azsdkLocalSPNFormatString = "AzSDK_CA_SPN_*" + + Write-Host "`nStep 2 of 3:Checking role assignments for subscription [$($SubscriptionId)] for AzSK SPNs..." + # check subscription scope role assignments + $azskSPNRoleAssignments = @() + $azskSPNRoleAssignments += Get-AzRoleAssignment | Where-Object { ($_.DisplayName -Like $azskLocalSPNFormatString) -or ($_.DisplayName -Like $azsdkLocalSPNFormatString ) } + + + if ($azskSPNRoleAssignments) { + Write-Host "`tRole assignments for SPNs are:`n" + $azskSPNRoleAssignments | Select-Object "DisplayName", "RoleDefinitionName", "Scope" | Format-Table + Write-host "WARNING: Before deleting role assignments please make sure that AAD applications & SPNs are not used anywhere else." -ForegroundColor Yellow + Write-Host "------------------------------------------------------" + Write-Host "`nStep 3 of 3:Please confirm deletion of all above listed assignemnts: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $userChoice = "" + + $userChoice = Read_UserChoice + if ($userChoice -eq 'Y') { + try { + Delete_RoleAssignments -AzskRoleAssignments $azskSPNRoleAssignments + Write-Host "Successfully deleted role assignments for AzSK SPNs." -ForegroundColor Green + } + catch { + Write-Host "ERROR: There was error while removing role assignments for AzSK SPNs." -ForegroundColor DarkYellow + } + } + else { + Write-Host "Skipped deletion for role assignments." -ForegroundColor Yellow + } + } + else { + Write-Host "No role assignemnts exists for AzSK SPNs." -ForegroundColor Green + } +} \ No newline at end of file diff --git a/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNs.ps1 b/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNs.ps1 new file mode 100644 index 00000000..a54421f7 --- /dev/null +++ b/14-Transition-and-Cleanup/scripts/DeleteAzSKSPNs.ps1 @@ -0,0 +1,121 @@ +function Pre_requisites { + <# + .SYNOPSIS + This command would check pre requisities modules. + .DESCRIPTION + This command would check pre requisities modules to perform clean-up. +#> + + Write-Host "Required modules are: Az.Resources, Az.Accounts, AzureAD" -ForegroundColor Cyan + Write-Host "Checking for required modules..." + $availableModules = $(Get-Module -ListAvailable Az.Resources, Az.Accounts, AzureAD) + + # Checking if 'Az.Accounts' module is available or not. + if ($availableModules.Name -notcontains 'Az.Accounts') { + Write-Host "Installing module Az.Accounts..." -ForegroundColor Yellow + Install-Module -Name Az.Accounts -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Accounts module is available." -ForegroundColor Green + } + + # Checking if 'Az.Resources' module is available or not. + if ($availableModules.Name -notcontains 'Az.Resources') { + Write-Host "Installing module Az.Resources..." -ForegroundColor Yellow + Install-Module -Name Az.Resources -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "Az.Resources module is available." -ForegroundColor Green + } + # Checking if 'AzureAD' module is available or not. + if ($availableModules.Name -notcontains 'AzureAD') { + Write-Host "Installing module AzureAD..." -ForegroundColor Yellow + Install-Module -Name AzureAD -Scope CurrentUser -Repository 'PSGallery' + } + else { + Write-Host "AzureAD module is available." -ForegroundColor Green + } +} +function Read_UserChoice { + $userSelection = "" + while ($userSelection -ne 'Y' -and $userSelection -ne 'N') { + $userSelection = Read-Host "User choice" + if (-not [string]::IsNullOrWhiteSpace($userSelection)) { + $userSelection = $userSelection.Trim(); + } + } + + return $userSelection; +} +function Delete_AADApplication { + param ($AadAppId, $force) + + Write-Host "Deleting AAD application of AzSK SPN $($AadAppId).Do You want to continue?`n[Y]: Yes`n[N]: No" + if($force){ + $userChoice ='Y' + } + else { + Write-Host "`nPlease confirm deletion of SPN $($AadAppId).: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $userChoice = Read_UserChoice + } + if ($userChoice -eq 'Y') { + try { + $success = Remove-AzADApplication -ApplicationId $AadAppId -Force + # Added this check as remove-azadapplication not returning success true/false properly + $appStillExist = Get-AzADApplication -ApplicationId $AadAppId -ErrorAction SilentlyContinue + if ($appStillExist) { + throw; + } + Write-Host "Successfully deleted AAD application of AzSK SPN $($AadAppId)" -ForegroundColor Green + } + catch { + Write-Host "Error while deleting AAD application of AzSK SPN." -ForegroundColor DarkYellow + } + + } +} +Function Remove-AzSKSPN { + <# + .SYNOPSIS + This command will remove AzSK/AzSDK deployed SPNs from AAD.Please make sure to confirm these SPNs are not used for other purpose prior to running this script. + .DESCRIPTION + This command will remove AzSK/AzSDK deployed SPNs from AAD.Please make sure to confirm these SPNs are not used for other purpose prior to running this script. + .PARAMETER Force + Use this switch to avoid user confimration before deletion of SPNs. + #> + param ( + [switch] + $force + ) + + try { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host "------------------------------------------------------" + } + catch { + Write-Host "Error occured while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + Write-Host "Connecting to AzureAD..." + Connect-AzureAD + Write-Host "Connected to AzureAD" -ForegroundColor Green + + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + + #List SPNs + $objectId = (Get-AzureADUser -Filter "UserPrincipalName eq '$($(Get-AzContext).Account)'").ObjectId + $spnList = Get-AzureADUserOwnedObject -ObjectId $objectId | Where-Object { ($_.ObjectType -eq "ServicePrincipal") -and (($_.DisplayName -like "AzSK_CA_SPN*") -or ($_.DisplayName -like "AzSDK_CA_SPN*") ) } + Write-Host("`nList of SPNs for which current logged in user is Owner`n") + $spnList | Select-Object "DisplayName", "ObjectId", "AppId" | Format-Table + foreach ($spn in $spnList) { + Delete_AADApplication($spn.AppId, $force) + } +} + diff --git a/14-Transition-and-Cleanup/scripts/Remove_AzSK_Deployed_Resources.ps1 b/14-Transition-and-Cleanup/scripts/Remove_AzSK_Deployed_Resources.ps1 new file mode 100644 index 00000000..e2dd9cbb --- /dev/null +++ b/14-Transition-and-Cleanup/scripts/Remove_AzSK_Deployed_Resources.ps1 @@ -0,0 +1,945 @@ +function Pre_requisites +{ + <# + .SYNOPSIS + This command would check pre requisities modules. + .DESCRIPTION + This command would check pre requisities modules to perform clean-up. + #> + + Write-Host "Required modules are: Az.Resources, Az.Accounts, Az.Automation" -ForegroundColor Cyan + Write-Host "Checking for required modules..." + $availableModules = $(Get-Module -ListAvailable Az.Resources, Az.Accounts, Az.Automation) + + # Checking if 'Az.Accounts' module is available or not. + if($availableModules.Name -notcontains 'Az.Accounts') + { + Write-Host "Installing module Az.Accounts..." -ForegroundColor Yellow + Install-Module -Name Az.Accounts -Scope CurrentUser -Repository 'PSGallery' + } + else + { + Write-Host "Az.Accounts module is available." -ForegroundColor Green + } + + # Checking if 'Az.Resources' module is available or not. + if($availableModules.Name -notcontains 'Az.Resources') + { + Write-Host "Installing module Az.Resources..." -ForegroundColor Yellow + Install-Module -Name Az.Resources -Scope CurrentUser -Repository 'PSGallery' + } + else + { + Write-Host "Az.Resources module is available." -ForegroundColor Green + } + + # Checking if 'Az.Automation' module is available or not. + if($availableModules.Name -notcontains 'Az.Automation') + { + Write-Host "Installing module Az.Automation..." -ForegroundColor Yellow + Install-Module -Name Az.Automation -Scope CurrentUser -Repository 'PSGallery' + } + else + { + Write-Host "Az.Automation module is available." -ForegroundColor Green + } + +} + +function Read_UserChoice +{ + $userSelection = "" + while($userSelection -ne 'Y' -and $userSelection -ne 'N') + { + $userSelection = Read-Host "User choice" + if(-not [string]::IsNullOrWhiteSpace($userSelection)) + { + $userSelection = $userSelection.Trim(); + } + } + + return $userSelection; +} + +function Delete_StorageAccount +{ + param ($StorageAccount) + + Write-Host "Deleting AzSK storage account [$($storageAccount.Name)]..." + $success = Remove-AzResource -ResourceGroupName $azskRGName -ResourceName $storageAccount.Name -ResourceType 'Microsoft.Storage/storageAccounts' -Force + if(-not $success) + { + throw; + } + Write-Host "Successfully deleted AzSK storage account." -ForegroundColor Green +} + +function Delete_AutomationAccount +{ + param ($ExistingAutomationAccount) + + Write-Host "Deleting AzSK automation account [$($existingAutomationAccount.Name)]..." + $success = Remove-AzResource -ResourceGroupName $azskRGName -ResourceName $existingAutomationAccount.Name -ResourceType 'Microsoft.Automation/automationAccounts' -Force + if(-not $success) + { + throw; + } + Write-Host "Successfully deleted AzSK automation account." -ForegroundColor Green +} + +function Delete_RoleAssignments +{ + param ($AzskRoleAssignments) + + Write-Host "Deleting role assignments of AzSK CA SPN..." + $azskRoleAssignments | Remove-AzRoleAssignment + Write-Host "Successfully deleted role assignment of AzSK CA SPN." -ForegroundColor Green +} + +function Delete_AADApplication +{ + param ($AadApp) + + Write-Host "Deleting AAD application of AzSK CA SPN..." + $success = Remove-AzADApplication -ApplicationId $aadApp.ApplicationId -Force + # Added this check as remove-azadapplication not returing success true/false properly + $appStillExist = Get-AzADApplication -ApplicationId $aadApp.ApplicationId -ErrorAction SilentlyContinue + if($appStillExist) + { + throw; + } + Write-Host "Successfully deleted AAD application of AzSK CA SPN." -ForegroundColor Green +} + +function Remove-AzSKResources +{ + <# + .SYNOPSIS + This command would help in deleting the AzSK deployed Azure resources in subscription. + .DESCRIPTION + This command will list all resources deployed in AzSKRG and divide them in two list a). AzSK deployed resources b). Non-AzSK deployed resources and will provide option to clean AzSK deployed resources. + + .PARAMETER SubscriptionId + Enter subscription id of the subscription for which clean-up need to be performed. + .PARAMETER PerformPreReqCheck + Perform pre requisities check to ensure all required module to perform clean-up operation is available. + .PARAMETER Force + Switch to force deletion of AzSK resources without further user consent. + #> + + param ( + [string] + [Parameter(Mandatory = $true, HelpMessage="Enter subscription id for clean-up")] + $SubscriptionId, + + [switch] + $PerformPreReqCheck, + + [switch] + $Force + ) + + Write-Host "======================================================" + Write-Host "Starting to perform clean-up for subscription [$($SubscriptionId)]..." + Write-Host "------------------------------------------------------" + + if($PerformPreReqCheck) + { + try + { + Write-Host "Checking for pre-requisites..." + Pre_requisites + Write-Host "------------------------------------------------------" + } + catch + { + Write-Host "Error occured while checking pre-requisites. ErrorMessage [$($_)]" -ForegroundColor Red + break + } + } + + # Connect to AzAccount + $isContextSet = Get-AzContext + if ([string]::IsNullOrEmpty($isContextSet)) + { + Write-Host "Connecting to AzAccount..." + Connect-AzAccount + Write-Host "Connected to AzAccount" -ForegroundColor Green + } + + # Setting context for current subscription. + $currentSub = Set-AzContext -SubscriptionId $SubscriptionId -ErrorAction Stop -Force + + Write-Host "Metadata Details: `n SubscriptionId: [$($SubscriptionId)] `n AccountName: [$($currentSub.Account.Id)] `n AccountType: [$($currentSub.Account.Type)]" + Write-Host "------------------------------------------------------" + Write-Host "Starting with Subscription [$($SubscriptionId)]..." + + + Write-Host "`nStep 1 of 3: Validating whether the current user [$($currentSub.Account.Id)] have the required permissions to run the script for Subscription [$($SubscriptionId)]..." + + # Safe Check: Checking whether the current account is of type User + if($currentSub.Account.Type -ne "User") + { + Write-Host "WARNING: This script can only be run by user account type." -ForegroundColor Yellow + break; + } + + # Safe Check: Current user need to have Owner role for the subscription + $currentLoginRoleAssignments = Get-AzRoleAssignment -SignInName $currentSub.Account.Id -Scope "/subscriptions/$($SubscriptionId)" -IncludeClassicAdministrators; + + if(($currentLoginRoleAssignments | Where-Object { $_.RoleDefinitionName -eq "Owner" -or $_.RoleDefinitionName -match 'CoAdministrator' -or $_.RoleDefinitionName -like '*ServiceAdministrator*'} | Measure-Object).Count -le 0) + { + Write-Host "WARNING: This script can only be run by an Owner of subscription [$($SubscriptionId)] " -ForegroundColor Yellow + break; + } + else{ + Write-Host "User has all required permissions." -ForegroundColor Green + } + + # Declaring all AzSK resources name/pattern + $azskRGName = "AzSKRG" + $automationAccountName = "AzSKContinuousAssurance" + $azskRunbookNames = @('AzSKContinuousAssurance/Continuous_Assurance_Runbook', 'AzSKContinuousAssurance/Alert_Runbook', 'AzSKContinuousAssurance/Continuous_Assurance_ScanOnTrigger_Runbook') + $connectionAssetName = "AzureRunAsConnection" + $StorageAccountNamePattern= "^azsk\d{14}$" + $alertNamePattern = "AzSK_*_Alert*" + $azskLocalSPNFormatString = "AzSK_CA_SPN_*" + $azskActionGroupNames = @("AzSKAlertActionGroup", "AzSKCriticalAlertActionGroup", "ResourceDeploymentActionGroup") + + Write-Host "`nStep 2 of 3: Listing resources present under resource group [$($azskRGName)] in Subscription [$($SubscriptionId)]..." + + # Get AzSK RG + $azskRG = Get-AzResourceGroup $azskRGName -ErrorAction SilentlyContinue + + if(-not $azskRG) + { + Write-Host "AzSKRG is not present in subscription [$($SubscriptionId)]" -ForegroundColor Red + return; + } + + # declare all required variables + $allResources = @() + $azskResources = @() + $nonAzSKResources = @() + $errorCollection = @() + $userSkippedResources = @() + $existingAzSKRunbooks = @() + $nonAzSKRunbooks = @() + $azskRoleAssignments = @() + $deleteAzSKRG = $false + $caSPN = $null + $aadApp = $null + $aadAppDeleted = $false + $roleAssignmentRemoved = $false + $azskRGDeleted = $false + + # Get All resource in AzSKRG + $allResources += Get-AzResource -ResourceGroupName $azskRGName -ErrorAction Stop + + if(($allResources | Measure-Object).Count -gt 0) + { + # Check AzSK Stoarge account + $storageAccount = $allResources | Where-Object { $_.Name -match $StorageAccountNamePattern -and $_.ResourceType -eq "Microsoft.Storage/storageAccounts" } + if(($storageAccount|Measure-Object).Count -gt 0) + { + $azskResources += $storageAccount + } + + # Check AzSK continuous assurance automation accounts + $existingAutomationAccount = $allResources | Where-Object { $_.Name -eq $automationAccountName -and $_.ResourceType -eq "Microsoft.Automation/automationAccounts" } + if(($existingAutomationAccount|Measure-Object).Count -gt 0) + { + $azskResources += $existingAutomationAccount + + # Check AzSK runbooks + $existingAzSKRunbooks += $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Automation/automationAccounts/runbooks" -and $_.Name -in $azskRunbookNames} + if(($existingAzSKRunbooks |Measure-Object).Count -gt 0) + { + $azskResources += $existingAzSKRunbooks + } + + # Check non AzSK runbooks present in AzSK Automation account + $nonAzSKRunbooks += $allResources | Where-Object { $_.ResourceType -eq "Microsoft.Automation/automationAccounts/runbooks" -and $_.Name -like "$($automationAccountName)/*" -and $_.Name -notin $azskRunbookNames} + if($nonAzSKRunbooks) + { + $azskResources += $nonAzSKRunbooks + } + + + # Fetching appID of CA SPN + $connection = Get-AzAutomationConnection -AutomationAccountName $automationAccountName -ResourceGroupName $azskRGName -Name $connectionAssetName -ErrorAction SilentlyContinue + if($connection) + { + $appID = $connection.FieldDefinitionValues.ApplicationId + $caSPN = Get-AzADServicePrincipal -ServicePrincipalName $appID -ErrorAction SilentlyContinue + $aadAPP = Get-AzADApplication -ApplicationId $appID -ErrorAction SilentlyContinue + # Safe check: SPN display name should match AzSK specified name pattern + if(-not ($caSPN.DisplayName -like $azskLocalSPNFormatString)) + { + $caSPN = $null + $aadAPP = $null + } + } + + # Get role assignment of current SPN + if($caSPN) + { + $subscriptionScope = "/subscriptions/{0}" -f $SubscriptionId + $rgScope = "/subscriptions/{0}/resourcegroups/{1}" -f $SubscriptionId, $azskRGName + $spnObjectId = $caSPN.Id + + # check subscription scope 'reader' role assignment + $azskRoleAssignments += Get-AzRoleAssignment -Scope $subscriptionScope -RoleDefinitionName Reader | Where-Object { $_.ObjectId -eq $spnObjectId } + # check resource group scope 'contributor' role assignment + $azskRoleAssignments += Get-AzRoleAssignment -Scope $rgScope -RoleDefinitionName Contributor | Where-Object { $_.ObjectId -eq $spnObjectId } + + } + + } + + # Get the alerts + $configuredAlerts = $allResources | Where-Object {$_.ResourceType -eq "Microsoft.Insights/activityLogAlerts"-and $_.Name -like $alertNamePattern } + if($configuredAlerts) + { + $azskResources += $configuredAlerts + } + + # Get the Action Group + $actionGrps = $allResources | Where-Object { $_.ResourceType -eq "microsoft.insights/actiongroups" -and $_.Name -in $azskActionGroupNames} + if($actionGrps) + { + $azskResources += $actionGrps + } + + if($azskResources) + { + $nonAzSKResources += $allResources | Where-Object {$_.Id -inotin $azskResources.Id } + } + else + { + $nonAzSKResources += $allResources + } + + Write-Host "`nA) Listing details of SPN associated with current AzSK automation account:" + if($caSPN) + { + $caSPN | Select-Object "DisplayName", "ApplicationId" | Format-Table + + if($azskRoleAssignments) + { + Write-Host "`tRole assignments for SPN:" + $azskRoleAssignments | Select-Object "RoleDefinitionName", "Scope" | Format-Table + + } + } + else + { + Write-Host("No SPN found.`n") + } + + Write-Host "B) Listing AzSK resources present in AzSKRG:" + if($azskResources) + { + $azskResources | Select-Object Name, ResourceType | Format-Table + } + else{ + Write-Host "No such resources found.`n" + } + + Write-Host("C) Listing Non-AzSK resources are present in AzSKRG:") + if($nonAzSKResources) + { + $nonAzSKResources | Select-Object Name, ResourceType | Format-Table + } + else{ + Write-Host "No such resources found." + } + + Write-Host "`nStep 3 of 3: Cleaning resources present under resource group [$($azskRGName)] in Subscription [$($SubscriptionId)]..." + + if($azskResources) + { + $userChoice="" + if($force) + { + $userChoice="A" + Write-Host "`nForce parameter is set to 'True', no further consent required." -ForegroundColor Yellow + } + else + { + + Write-Host "Please select an action from below: `n[A]: Delete all AzSK deployed resources & AAD application `n[N]: Delete none`n[S]: Delete selected" -ForegroundColor Cyan + while($userChoice -ne 'A' -and $userChoice -ne 'N' -and $userChoice -ne 'S') + { + $userChoice = Read-Host "User choice" + if(-not [string]::IsNullOrWhiteSpace($userChoice)) + { + $userChoice = $userChoice.Trim(); + } + } + } + + + switch ($userChoice.ToUpper()) + { + "A" #DeleteAll + { + Write-Host "======================================================" + Write-Host "`nFollowing resources will be deleted:" + + Write-Host "------------------------------------------------------" + Write-Host "`tAzure resources:" -ForegroundColor Cyan + $azskResources | Select-Object Name, ResourceType | Format-Table + + if($caSPN) + { + Write-Host "------------------------------------------------------" + if($azskRoleAssignments) + { + Write-Host "`tRole assignments:" -ForegroundColor Cyan + $azskRoleAssignments | Select-Object "RoleDefinitionName", "Scope" | Format-Table + } + + Write-Host "`tAzure AD application:" -ForegroundColor Cyan + $caSPN | Select-Object DisplayName, ApplicationId | Format-Table + + Write-host "WARNING: Before deleting SPN & AAD Application [$($caSPN.DisplayName)], please make sure that this AAD application & SPN is not used anywhere else." -ForegroundColor Yellow + Write-Host "------------------------------------------------------" + + } + Write-Host "======================================================" + + $userChoice = "" + if($force) + { + $userChoice="Y" # No further user consent required as 'Force' switch is enabled + }else + { + Write-Host "`nPlease confirm deletion of all above listed resources: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + + $userChoice = Read_UserChoice + } + + + if($userChoice -ne "Y") + { + Write-Host "No resources were deleted." -ForegroundColor Yellow + $userSkippedResources = $azskResources + break; + } + + + + # Delete storage account if exists + if($storageAccount) + { + try + { + Delete_StorageAccount -StorageAccount $storageAccount + } + catch + { + $errorCollection += $storageAccount + Write-Host "Error occurred while deleting AzSK storage account [$($storageAccount.Name)]." -ForegroundColor DarkYellow + } + } + + # Delete automation account and all associated runbooks if exists + if($existingAutomationAccount) + { + try + { + Delete_AutomationAccount -ExistingAutomationAccount $existingAutomationAccount + } + catch + { + $errorCollection += $existingAutomationAccount + $errorCollection += $existingAzSKRunbooks + Write-Host "Error occurred while deleting AzSK automation account [$($existingAutomationAccount.Name)]." -ForegroundColor DarkYellow + } + } + + # Delete the alerts if exist + if($configuredAlerts) + { + $errorCount = 0 + Write-Host "Deleting AzSK alerts..." + $configuredAlerts | ForEach-Object { + $alertName = $_.Name; + $alert = $_; + # Remove alert + try + { + $success = Remove-AzResource -ResourceType "Microsoft.Insights/activityLogAlerts" -ResourceGroupName $azskRGName -Name $alertName -Force + if(-not $success) + { + throw; + } + } + catch + { + $errorCount += 1; + $errorCollection += $alert + } + } + + if($errorCount -gt 0) + { + Write-Host "Error occurred while deleting AzSK alerts." -ForegroundColor DarkYellow + }else{ + Write-Host "Successfully deleted AzSK alerts." -ForegroundColor Green + } + } + + # Delete the action groups if exist + if($actionGrps) + { + Write-Host "Deleting AzSK action groups..." + $errorCount = 0 + $actionGrps | ForEach-Object { + $actionGroupName = $_.Name; + $actionGroup = $_; + try + { + $success = Remove-AzResource -ResourceType "Microsoft.Insights/actiongroups" -ResourceGroupName $azskRGName -Name $actionGroupName -Force + if(-not $success) + { + throw; + } + } + catch + { + $errorCount += 1; + $errorCollection += $actionGroup + } + } + + if($errorCount -gt 0) + { + Write-Host "Error occurred while deleting AzSK action groups." -ForegroundColor DarkYellow + }else{ + Write-Host "Successfully deleted AzSK action groups." -ForegroundColor Green + } + } + + # Delete role assignments + if($azskRoleAssignments) + { + try + { + Delete_RoleAssignments -AzskRoleAssignments $azskRoleAssignments + $roleAssignmentRemoved = $true + } + catch + { + Write-Host "ERROR: There was some error while removing role assignment for AzSK SPN." -ForegroundColor DarkYellow + } + } + + # Delete the AAD Application + if($aadApp) + { + try + { + Delete_AADApplication -AadApp $aadApp + $aadAppDeleted = $true + } + catch + { + Write-Host "ERROR: There was an error while deleting the AAD application. You may not have 'Owner' permission on it." -ForegroundColor DarkYellow + } + } + + break + } + "N" #None + { + Write-Host "Process aborted. No resources were deleted." -ForegroundColor Yellow + $userSkippedResources = $azskResources + return; + break + } + "S" #Select + { + Write-Host "======================================================" + # Delete storage account if exists and user confirms + if($storageAccount) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK storage account: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $storageAccount | Select-Object Name, ResourceType | Format-Table + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + try + { + Delete_StorageAccount -StorageAccount $storageAccount + } + catch + { + $errorCollection += $storageAccount + Write-Host "Error occurred while deleting AzSK storage account [$($storageAccount.Name)]." -ForegroundColor DarkYellow + } + } + else + { + $userSkippedResources += $storageAccount + Write-Host "Skipped deletion of AzSK storage account [$($storageAccount.Name)]." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + + } + + # Delete automation account and all associated runbooks if exists + if($existingAutomationAccount) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK automation account and all associated runbooks: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + (@($existingAutomationAccount) + $existingAzSKRunbooks) | Select-Object Name, ResourceType | Format-Table + + + if($nonAzSKRunbooks) + { + Write-Host "WARNING: Following Non-AzSK deployed runbooks are also present in AzSK automation account, if you choose to delete AzSK automation account these runbooks will also be deleted." -ForegroundColor Yellow + $nonAzSKRunbooks | Select-Object Name, ResourceType | Format-Table + } + + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + + try + { + Delete_AutomationAccount -ExistingAutomationAccount $existingAutomationAccount + } + catch + { + $errorCollection += $existingAutomationAccount + $errorCollection += $existingAzSKRunbooks + Write-Host "Error occurred while deleting AzSK automation account [$($existingAutomationAccount.Name)]." -ForegroundColor DarkYellow + } + } + else + { + $userSkippedResources += $existingAutomationAccount + $userSkippedResources += $existingAzSKRunbooks + Write-Host "Skipped deletion of AzSK automation account [$($existingAutomationAccount.Name)]." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + } + + # Delete the alerts if exist + if($configuredAlerts) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK alerts: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $configuredAlerts | Select-Object Name, ResourceType | Format-Table + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + $errorCount = 0 + Write-Host "Deleting AzSK alerts..." + $configuredAlerts | ForEach-Object { + $alertName = $_.Name; + $alert = $_; + # Remove alert + try + { + $success = Remove-AzResource -ResourceType "Microsoft.Insights/activityLogAlerts" -ResourceGroupName $azskRGName -Name $alertName -Force + if(-not $success) + { + throw; + } + } + catch + { + $errorCount += 1; + $errorCollection += $alert + } + } + + if($errorCount -gt 0) + { + Write-Host "Error occurred while deleting AzSK alerts." -ForegroundColor DarkYellow + }else{ + Write-Host "Successfully deleted AzSK alerts." -ForegroundColor Green + } + } + else + { + $userSkippedResources += $configuredAlerts + Write-Host "Skipped deletion of AzSK alerts." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + } + + # Delete the action groups if exist + if($actionGrps) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK alert action groups: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $actionGrps | Select-Object Name, ResourceType | Format-Table + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + + Write-Host "Deleting AzSK action groups..." + $errorCount = 0 + $actionGrps | ForEach-Object { + $actionGroupName = $_.Name; + $actionGroup = $_; + try + { + $success = Remove-AzResource -ResourceType "Microsoft.Insights/actiongroups" -ResourceGroupName $azskRGName -Name $actionGroupName -Force + if(-not $success) + { + throw; + } + } + catch + { + $errorCount += 1; + $errorCollection += $actionGroup + } + } + + if($errorCount -gt 0) + { + Write-Host "Error occurred while deleting AzSK action groups." -ForegroundColor DarkYellow + }else{ + Write-Host "Successfully deleted AzSK action groups." -ForegroundColor Green + } + } + else + { + $userSkippedResources += $actionGrps + Write-Host "Skipped deletion of AzSK alert action groups." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + } + + Write-Host "======================================================" + + # Delete the SPN role assignment + if($azskRoleAssignments) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK SPN role assignments: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $azskRoleAssignments | Select-Object "RoleDefinitionName", "Scope" | Format-Table + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + try + { + Delete_RoleAssignments -AzskRoleAssignments $azskRoleAssignments + $roleAssignmentRemoved = $true + } + catch + { + Write-Host "ERROR: There was some error while removing role assignment for AzSK SPN." -ForegroundColor DarkYellow + } + } + else + { + Write-Host "Skipped deletion of role assignments." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + } + + # Delete the AAD Application + if($aadApp) + { + Write-Host "------------------------------------------------------" + Write-Host "`nDo you want to delete AzSK CA SPN/Application: `n[Y]: Yes`n[N]: No" -ForegroundColor Cyan + $aadApp | Select-Object DisplayName, ApplicationId | Format-Table + Write-host "WARNING: Before deleting SPN & AAD Application [$($caSPN.DisplayName)], please make sure that this AAD application & SPN is not used anywhere else." -ForegroundColor Yellow + + $userChoice="" + $userChoice = Read_UserChoice + + if($userChoice -eq 'Y') + { + try + { + Delete_AADApplication -AadApp $aadApp + $aadAppDeleted = $true + } + catch + { + Write-Host "ERROR: There was an error while deleting the AAD application. You may not have 'Owner' permission on it." -ForegroundColor DarkYellow + } + } + else + { + Write-Host "Skipped deletion of AzSK CA SPN/Application." -ForegroundColor Yellow + } + Write-Host "------------------------------------------------------" + } + Write-Host "======================================================" + + break + } + + } + + } + + try + { + $allResources = Get-AzResource -ResourceGroupName $azskRGName + + if(($allResources | Measure-Object).Count -gt 0) + { + Write-Host "======================================================" + $deleteAzSKRG = $false + if($nonAzSKResources) + { + Write-Host "`nFollowing Non-AzSK resources are present in AzSKRG, please move/delete these resources before deleting AzSKRG." -ForegroundColor Yellow + $nonAzSKResources | Select-Object Name, ResourceType | Format-Table + } + + if($errorCollection){ + Write-Host "`nError occurred while deleting following resources, please delete these resources manually from portal or contact support team." -ForegroundColor Red + $errorCollection | Select-Object Name, ResourceType | Format-Table + } + + if($userSkippedResources){ + Write-Host "`nFollowing AzSK resources were skipped from deletion based on your selection, AzSKRG will not be deleted." -ForegroundColor Yellow + $userSkippedResources | Select-Object Name, ResourceType | Format-Table + } + + } + else + { + $deleteAzSKRG = $true + } + } + catch{ + $deleteAzSKRG = $false + } + + } + else{ + $deleteAzSKRG = $true + Write-Host "No resources found in AzSKRG." -ForegroundColor Yellow + } + + # Delete AzSKRG + Write-Host "------------------------------------------------------" + if($deleteAzSKRG) + { + try + { + Write-Host "Deleting AzSK resource group [$($azskRGName)] from subscription [$($SubscriptionId)]..." + $success = Remove-AzResourceGroup -Name $azskRGName -Force + if(-not $success) + { + throw; + } + $azskRGDeleted = $true + Write-Host "Successfully deleted AzSK resource group [$($azskRGName)] from subscription [$($SubscriptionId)]" -ForegroundColor Green + } + catch + { + Write-Host "ERROR: Error occurred while deleting resource group [$($azskRGName)], please contact support team." -ForegroundColor Red + } + + } + else + { + Write-Host "WARNING: Deletion of AzSK resource group [$($azskRGName)] skipped." -ForegroundColor Yellow + } + Write-Host "======================================================" -ForegroundColor Cyan + + # Summary + Write-Host "*** Summary ***" -ForegroundColor Cyan + Write-Host "------------------------------------------------------" + Write-Host "Following Azure resources were deleted:" + $resourcesNotRemoved = $errorCollection + $userSkippedResources + $deletedResources = Compare-Object -ReferenceObject $azskResources -DifferenceObject $resourcesNotRemoved -Property ReourceId -PassThru + if($deletedResources) + { + $deletedResources | Select-Object Name, ResourceType | Format-Table + } + else + { + Write-Host "`n`tNo resources were deleted." + } + + Write-Host "------------------------------------------------------" + Write-Host "Following role assignments were removed:" + + if($roleAssignmentRemoved) + { + $azskRoleAssignments | Select-Object "RoleDefinitionName", "Scope" | Format-Table + } + else + { + Write-Host "`n`tNo role assignment removed." + } + + Write-Host "------------------------------------------------------" + Write-Host "Following AAD App & SPN were deleted:" + + if($aadAppDeleted) + { + $aadApp | Select-Object DisplayName, ApplicationId | Format-Table + } + else + { + Write-Host "`n`tNo AAD App & SPN deleted." + } + Write-Host "------------------------------------------------------" + Write-Host "======================================================" -ForegroundColor Cyan + + # Next Steps + Write-Host "*** Next steps ***" -ForegroundColor Cyan + $success = $true + if(-not $azskRGDeleted) + { + Write-Host "[$($azskRGName)] is not removed from subscription [$($SubscriptionId)], please look at the wanrings/errors listed above after step #3." + Write-Host "`ta) If there is any Non-AzSK resources present in $($azskRGName), please remove/delete those resources using Azure portal." + Write-Host "`tb) If there is any error occurred while deleting AzSK resources, please look at the error details to resolve or try deleting such resources from Azure portal." + Write-Host "`tc) If you choose to skip deletion of selected resourecs then no further action needed." + $success = $success -and $false + } + + if($aadApp -and -not($aadAppDeleted)) + { + Write-Host "AAD application [$($aadApp.DisplayName)] is not deleted." + Write-Host "`ta) You may not have owner permission on the application, please request owner of the application to delete using Azure portal." + Write-Host "`tb) If you choose to skip deletion of AAD Application then no further action needed." + $success = $success -and $false + } + + if($azskRoleAssignments -and -not($roleAssignmentRemoved)) + { + Write-Host "Role assignment of AzSK CA SPN is not successfully removed." + Write-Host "`ta) Please look at the error details above for more details or you can also remove role assignment using Azure portal." + Write-Host "`tb) If you choose to skip deletion of CA SPN's role assignments then no further action needed." + $success = $success -and $false + } + + if($success) + { + Write-Host "No further action needed." -ForegroundColor Green + } + + Write-Host "======================================================" -ForegroundColor Cyan + +} + + + + + diff --git a/ARMTemplates/AnalysisServices.json b/ARMTemplates/AnalysisServices.json new file mode 100644 index 00000000..4d9d8d52 --- /dev/null +++ b/ARMTemplates/AnalysisServices.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "serverName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Analysis Services server to create. Server name must begin with a letter, be lowercase alphanumeric, and between 3 and 63 characters in length. Server name must be unique per region." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location of all resources." + } + }, + "serverLocation": { + "type": "string", + "defaultValue": "North Central US", + "metadata": { + "description": "Location of the Azure Analysis Services server. For supported regions, see https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" + } + }, + "skuName": { + "type": "string", + "defaultValue": "S0", + "metadata": { + "description": "The sku name of the Azure Analysis Services server to create. Choose from: B1, B2, D1, S0, S1, S2, S3, S4, S8, S9. Some skus are region specific. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" + } + }, + "capacity": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "The total number of query replica scale-out instances. Scale-out of more than one instance is supported on selected regions only. See https://docs.microsoft.com/en-us/azure/analysis-services/analysis-services-overview#availability-by-region" + } + }, + "firewallSettings": { + "type": "object", + "defaultValue": { + "firewallRules": [ + { + "firewallRuleName": "Rule Name", + "rangeStart": "start IP range", // Do not enter full IP range + "rangeEnd": "end IP range" + } + ], + "enablePowerBIService": true + }, + "metadata": { + "description": "The inbound firewall rules to define on the server. If not specified, firewall is disabled." + } + }, + "members": { + "type": "array", + "defaultValue": [ "user@contoso.com" ], + "metadata": { + "description": "" + } + } + }, + "resources": [ + { + "apiVersion": "2017-08-01", + "type": "Microsoft.AnalysisServices/servers", + "name": "[parameters('serverName')]", + "location": "[parameters('serverLocation')]", + "sku": { + "name": "[parameters('skuName')]", + "capacity": "[parameters('capacity')]" + }, + "properties": { + "asAdministrators": { + "members": "[parameters('members')]" + }, + "ipV4FirewallSettings": "[parameters('firewallSettings')]", + "backupBlobContainerUri": "Backup Blob Container Uri" //The SAS URI to a private Azure Blob Storage container with read, write and list permissions. Required only if you intend to use the backup/restore functionality. + } + } + ] + } diff --git a/ARMTemplates/AppService.json b/ARMTemplates/AppService.json index 8a189468..60fc32d9 100644 --- a/ARMTemplates/AppService.json +++ b/ARMTemplates/AppService.json @@ -41,25 +41,35 @@ }, { - "name": "[parameters('appservicename')]", - "type": "Microsoft.Web/sites", - "apiVersion": "2016-08-01", - "location": "[parameters('location')]", - "properties": { - "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('serviceplanname'))]", - "siteConfig": { - "alwaysOn": true, //[Azure_AppService_BCDR_Use_AlwaysOn] enable 'always on' - "use32BitWorkerProcess": false, - "requestTracingEnabled": true, //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring - "httpLoggingEnabled": true, //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring - "detailedErrorLoggingEnabled": true //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring - - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Web/serverfarms', parameters('serviceplanname'))]" - ] - } + "name": "[parameters('appservicename')]", + "type": "Microsoft.Web/sites", + "apiVersion": "2016-08-01", + "location": "[parameters('location')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('serviceplanname'))]", + "httpsOnly": true, //[Azure_AppService_DP_Dont_Allow_HTTP_Access] + "siteConfig": { + "alwaysOn": true, //[Azure_AppService_BCDR_Use_AlwaysOn] enable 'always on'] + "use32BitWorkerProcess": false, + "requestTracingEnabled": true, //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring + "httpLoggingEnabled": true, //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring + "detailedErrorLoggingEnabled": true, //[Azure_AppService_Audit_Enable_Logging_and_Monitoring] enable auditing and monitoring + "remoteDebuggingEnabled": false, //[Azure_AppService_Config_Disable_Remote_Debugging] + "webSocketsEnabled": false, //[Azure_AppService_Config_Disable_Web_Sockets] + "siteAuthEnabled":true, //[Azure_AppService_AuthN_Use_AAD_for_Client_AuthN] + "netFrameworkVersion":"v4.7",// [Azure_AppService_Deploy_Use_Latest_Version] + "siteAuthSettings":{ + "clientId":"***********ClientId*********" //[Azure_AppService_AuthN_Use_AAD_for_Client_AuthN] + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', parameters('serviceplanname'))]" + ] + } ] -} \ No newline at end of file +} diff --git a/ARMTemplates/Databricks.json b/ARMTemplates/Databricks.json new file mode 100644 index 00000000..5c55c18a --- /dev/null +++ b/ARMTemplates/Databricks.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "workspaceName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Databricks workspace to create." + } + }, + "pricingTier": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium" + ], + "metadata": { + "description": "The pricing tier of workspace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "variables": { + "managedResourceGroupName": "[concat('databricks-rg-', parameters('workspaceName'), '-', uniqueString(parameters('workspaceName'), resourceGroup().id))]" + }, + "resources": [ + { + "type": "Microsoft.Databricks/workspaces", + "name": "[parameters('workspaceName')]", + "location": "[parameters('location')]", + "apiVersion": "2018-04-01", + "sku": { + "name": "[parameters('pricingTier')]" + }, + "properties": { + "ManagedResourceGroupId": "[concat(subscription().id, '/resourceGroups/', variables('managedResourceGroupName'))]" + } + } + ], + "outputs": { + "workspace": { + "type": "object", + "value": "[reference(resourceId('Microsoft.Databricks/workspaces', parameters('workspaceName')))]" + } + } + } \ No newline at end of file diff --git a/ARMTemplates/HDInsight.json b/ARMTemplates/HDInsight.json new file mode 100644 index 00000000..21cc5a4c --- /dev/null +++ b/ARMTemplates/HDInsight.json @@ -0,0 +1,150 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "clusterName": { + "type": "string", + "metadata": { + "description": "The name of the HDInsight cluster to create." + } + }, + "clusterType": { + "type": "string", + "allowedValues": [ + "hadoop", + "intractivehive", + "hbase", + "storm", + "spark" + ], + "metadata": { + "description": "The type of the HDInsight cluster to create." + } + }, + "clusterLoginUserName": { + "type": "string", + "metadata": { + "description": "These credentials can be used to submit jobs to the cluster and to log into cluster dashboards." + } + }, + "clusterLoginPassword": { + "type": "securestring", + "metadata": { + "description": "The password must be at least 10 characters in length and must contain at least one digit, one non-alphanumeric character, and one upper or lower case letter." + } + }, + "sshUserName": { + "type": "string", + "metadata": { + "description": "These credentials can be used to remotely access the cluster." + } + }, + "sshPassword": { + "type": "securestring", + "metadata": { + "description": "The password must be at least 10 characters in length and must contain at least one digit, one non-alphanumeric character, and one upper or lower case letter." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "variables": { + "defaultStorageAccount": { + "name": "[uniqueString(resourceGroup().id)]", + "type": "Standard_LRS" + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "name": "[variables('defaultStorageAccount').name]", + "location": "[parameters('location')]", + "apiVersion": "2016-01-01", + "sku": { + "name": "[variables('defaultStorageAccount').type]" + }, + "kind": "Storage", + "properties": { + "supportsHttpsTrafficOnly": true + } + }, + { + "type": "Microsoft.HDInsight/clusters", + "name": "[parameters('clusterName')]", + "location": "[parameters('location')]", + "apiVersion": "2015-03-01-preview", + "dependsOn": [ + "[concat('Microsoft.Storage/storageAccounts/',variables('defaultStorageAccount').name)]" + ], + "properties": { + "clusterVersion": "3.6.1000.67", + "osType": "Linux", + "clusterDefinition": { + "kind": "[parameters('clusterType')]", + "configurations": { + "gateway": { + "restAuthCredential.isEnabled": true, + "restAuthCredential.username": "[parameters('clusterLoginUserName')]", + "restAuthCredential.password": "[parameters('clusterLoginPassword')]" + } + } + }, + "storageProfile": { + "storageaccounts": [ + { + "name": "[replace(replace(concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('defaultStorageAccount').name), '2016-01-01').primaryEndpoints.blob),'https:',''),'/','')]", + "isDefault": true, + "container": "[parameters('clusterName')]", + "key": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('defaultStorageAccount').name), '2016-01-01').keys[0].value]" + } + ] + }, + "computeProfile": { + "roles": [ + { + "name": "headnode", + "targetInstanceCount": 2, + "hardwareProfile": { + "vmSize": "Standard_D3_v2" + }, + "osProfile": { + "linuxOperatingSystemProfile": { + "username": "[parameters('sshUserName')]", + "password": "[parameters('sshPassword')]" + } + } + }, + { + "name": "workernode", + "targetInstanceCount": 2, + "hardwareProfile": { + "vmSize": "Standard_D3_v2" + }, + "osProfile": { + "linuxOperatingSystemProfile": { + "username": "[parameters('sshUserName')]", + "password": "[parameters('sshPassword')]" + } + } + } + ] + } + } + } + ], + "outputs": { + "storage": { + "type": "object", + "value": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('defaultStorageAccount').name))]" + }, + "cluster": { + "type": "object", + "value": "[reference(resourceId('Microsoft.HDInsight/clusters',parameters('clusterName')))]" + } + } +} \ No newline at end of file diff --git a/ARMTemplates/KeyVault.json b/ARMTemplates/KeyVault.json index eb884e96..ed301397 100644 --- a/ARMTemplates/KeyVault.json +++ b/ARMTemplates/KeyVault.json @@ -11,12 +11,12 @@ "tenantId": { "type": "string", "metadata": { - "description": "Tenant Id for the subscription and use assigned access to the vault. Available from the Get-AzureRMSubscription PowerShell cmdlet" + "description": "Tenant Id for the subscription and use assigned access to the vault. Available from the Get-AzSubscription PowerShell cmdlet" } }, "accessPolicies": { "type": "array", - "defaultValue": [ ], + "defaultValue": [], "metadata": { "description": "Access policies object to define access policies" } @@ -39,6 +39,13 @@ "description": "Specifies if the vault is enabled for VM or Service Fabric deployment" } }, + "enabledForDiskEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Specifies if the vault is enabled for Disk Encryption" + } + }, "enabledForTemplateDeployment": { "type": "bool", "defaultValue": false, @@ -67,53 +74,54 @@ "apiVersion": "2015-06-01", "location": "[resourceGroup().location]", "resources": [ - { - - "type": "providers/diagnosticSettings",//[Azure_KeyVault_Audit_Enable_Diagnostics_Log] - "name": "Microsoft.Insights/service", - "dependsOn": [ - "[resourceId('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]" - ], - "apiVersion": "2015-07-01", - "properties": { - "storageAccountId":"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountNameForDiagnostics'))]", - "logs": [ - { - "category": "AuditEvent", - "enabled": true, - "retentionPolicy": { - "days": 365, - "enabled": true - } - } - ], - "metrics": [ - { - "timeGrain": "PT1M", - "enabled": true, - "retentionPolicy": { - "enabled": true, - "days": 365 - } + { + "type": "providers/diagnosticSettings", //[Azure_KeyVault_Audit_Enable_Diagnostics_Log] + "name": "Microsoft.Insights/service", + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]" + ], + "apiVersion": "2015-07-01", + "properties": { + "storageAccountId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountNameForDiagnostics'))]", + "logs": [ + { + "category": "AuditEvent", + "enabled": true, + "retentionPolicy": { + "days": 365, + "enabled": true + } + } + ], + "metrics": [ + { + "timeGrain": "PT1M", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": 365 + } + } + ] } - ] - } - } - ], + } + ], "tags": { "displayName": "KeyVault" }, "properties": { + "enableSoftDelete" : true, + "enabledForDiskEncryption" : "[parameters('enabledForDiskEncryption')]", "enabledForDeployment": "[parameters('enabledForDeployment')]", - "enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",//[Azure_KeyVault_AuthZ_Configure_Advanced_Access_Policies] - "enabledForVolumeEncryption": "[parameters('enableVaultForVolumeEncryption')]",//[Azure_KeyVault_AuthZ_Configure_Advanced_Access_Policies] + "enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]", //[Azure_KeyVault_AuthZ_Configure_Advanced_Access_Policies] + "enabledForVolumeEncryption": "[parameters('enableVaultForVolumeEncryption')]", //[Azure_KeyVault_AuthZ_Configure_Advanced_Access_Policies] "tenantId": "[parameters('tenantId')]", - "accessPolicies": "[parameters('accessPolicies')]",//[Azure_KeyVault_AuthZ_Grant_Min_Access_policies] + "accessPolicies": "[parameters('accessPolicies')]", //[Azure_KeyVault_AuthZ_Grant_Min_Access_policies] "sku": { "name": "[parameters('vaultSku')]", "family": "A" - } - } + } + } } ] } \ No newline at end of file diff --git a/ARMTemplates/MySQL.json b/ARMTemplates/MySQL.json new file mode 100644 index 00000000..dd66ff6c --- /dev/null +++ b/ARMTemplates/MySQL.json @@ -0,0 +1,91 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "servers_mysqldbserver_name": { + "defaultValue": "mysqldbserver", + "type": "String" + }, + "MySQL_Location": { + "defaultValue": "Enter MySQL Database location", + "type": "String" + }, + "sku_name": { + "defaultValue": "Enter sku name", + "type": "String" + }, + "sku_tier": { + "defaultValue": "Enter sku tier", + "type": "String" + }, + "sku_generation": { + "defaultValue": "Enter sku generation", + "type": "String" + }, + "storageMB": { + "defaultValue": "Enter storageMB", + "type": "int" + }, + "version": { + "defaultValue": "Enter version", + "type": "int" + }, + "start_IP": { + "defaultValue": "Enter start_IP", + "type": "String" + }, + "end_IP": { + "defaultValue": "Enter end_IP", + "type": "String" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.DBforMySQL/servers", + "apiVersion": "2017-12-01", + "name": "[parameters('servers_mysqldbserver_name')]", + "location": "[parameters('MySQL_Location')]", + "sku": { + "name": "[parameters('sku_name')]", + "tier": "[parameters('sku_tier')]", + "family": "[parameters('sku_generation')]", + "capacity": 2 + }, + "properties": { + "storageProfile": { + "storageMB": "[parameters('storageMB')]", + "backupRetentionDays": 7, + "geoRedundantBackup": "Disabled", + "storageAutoGrow": "Disabled" + }, + "version": "[parameters('version')]", + "sslEnforcement": "Enabled" + } + }, + { + "type": "Microsoft.DBforMySQL/servers/firewallRules", + "apiVersion": "2017-12-01", + "name": "[concat(parameters('servers_mysqldbserver_name'), '/AllowAll')]", + "dependsOn": [ + "[resourceId('Microsoft.DBforMySQL/servers', parameters('servers_mysqldbserver_name'))]" + ], + "properties": { + "startIpAddress": "[parameters('start_IP')]", // start and end IP address should not be Any-to-Any i.e 0.0.0.0-255.255.255.255 + "endIpAddress": "[parameters('end_IP')]" + } + }, + { + "type": "Microsoft.DBforMySQL/servers/firewallRules", + "apiVersion": "2017-12-01", + "name": "[concat(parameters('servers_mysqldbserver_name'), '/AllowAllWindowsAzureIps')]", + "dependsOn": [ + "[resourceId('Microsoft.DBforMySQL/servers', parameters('servers_mysqldbserver_name'))]" + ], + "properties": { + "startIpAddress": "0.0.0.0", // If startIpAddress and endIpAddress is 0.0.0.0 that means AllowAllWindowsAzureIps turned on. + "endIpAddress": "0.0.0.0" + } + } + ] +} \ No newline at end of file diff --git a/ARMTemplates/PostgreSQL.json b/ARMTemplates/PostgreSQL.json new file mode 100644 index 00000000..8187f6f0 --- /dev/null +++ b/ARMTemplates/PostgreSQL.json @@ -0,0 +1,175 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "siteName": { + "type": "string", + "metadata": { + "description": "Name of azure web app" + } + }, + "administratorLogin": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Database administrator login name" + } + }, + "administratorLoginPassword": { + "type": "securestring", + "minLength": 8, + "maxLength": 128, + "metadata": { + "description": "Database administrator password" + } + }, + "databaseSkuCapacity": { + "type": "int", + "defaultValue": 2, + "allowedValues": [ + 2, + 4, + 8, + 16, + 32 + ], + "metadata": { + "description": "Azure database for PostgreSQL compute capacity in vCores (2,4,8,16,32)" + } + }, + "databaseSkuName": { + "type": "string", + "defaultValue": "GP_Gen5_2", + "allowedValues": [ + "GP_Gen5_2", + "GP_Gen5_4", + "GP_Gen5_8", + "GP_Gen5_16", + "GP_Gen5_32", + "MO_Gen5_2", + "MO_Gen5_4", + "MO_Gen5_8", + "MO_Gen5_16", + "MO_Gen5_32" + ], + "metadata": { + "description": "Azure database for PostgreSQL sku name " + } + }, + "databaseSkuSizeMB": { + "type": "int", + "allowedValues": [ + 102400, + 51200 + ], + "defaultValue": 51200, + "metadata": { + "description": "Azure database for PostgreSQL Sku Size " + } + }, + "databaseSkuTier": { + "type": "string", + "defaultValue": "GeneralPurpose", + "allowedValues": [ + "GeneralPurpose", + "MemoryOptimized" + ], + "metadata": { + "description": "Azure database for PostgreSQL pricing tier" + } + }, + "postgresqlVersion": { + "type": "string", + "allowedValues": [ + "9.5", + "9.6" + ], + "defaultValue": "9.6", + "metadata": { + "description": "PostgreSQL version" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + }, + "databaseskuFamily": { + "type": "string", + "defaultValue": "Gen5", + "metadata": { + "description": "Azure database for PostgreSQL sku family" + } + }, + "start_IP": { + "type": "String" + "defaultValue": "Enter start_IP", + "metadata":{ + "description": "Enter start IP address" + } + }, + "end_IP": { + "type": "String" + "defaultValue": "Enter end_IP", + "metadata":{ + "description": "Enter end IP address" + } + } + }, + "variables": { + "databaseName": "[concat(parameters('siteName'), 'database')]", + "serverName": "[concat(parameters('siteName'), 'pgserver')]", + "hostingPlanName": "[concat(parameters('siteName'), 'serviceplan')]" + }, + "resources": [ + { + "apiVersion": "2017-12-01", + "type": "Microsoft.DBforPostgreSQL/servers", + "location": "[parameters('location')]", + "name": "[variables('serverName')]", + "sku": { + "name": "[parameters('databaseSkuName')]", + "tier": "[parameters('databaseSkuTier')]", + "capacity": "[parameters('databaseSkucapacity')]", + "size": "[parameters('databaseSkuSizeMB')]", + "family": "[parameters('databaseskuFamily')]" + }, + "properties": { + "version": "[parameters('postgresqlVersion')]", + "administratorLogin": "[parameters('administratorLogin')]", + "administratorLoginPassword": "[parameters('administratorLoginPassword')]", + "storageMB": "[parameters('databaseSkuSizeMB')]", + "sslEnforcement": "Enabled" // SSL Enforcement + }, + "resources": [ + { + "type": "firewallrules", + "apiVersion": "2017-12-01", + "dependsOn": [ + "[concat('Microsoft.DBforPostgreSQL/servers/', variables('serverName'))]" + ], + "location": "[parameters('location')]", + "name": "[concat(variables('serverName'),'firewall')]", + "properties": { + "startIpAddress": "[parameters('start_IP')]", + "endIpAddress": "[parameters('end_IP')]" + } + }, + { + "name": "[variables('databaseName')]", + "type": "databases", + "apiVersion": "2017-12-01", + "properties": { + "charset": "utf8", + "collation": "English_United States.1252" + }, + "dependsOn": [ + "[concat('Microsoft.DBforPostgreSQL/servers/', variables('serverName'))]" + ] + } + ] + } + ] +} diff --git a/ARMTemplates/Readme.md b/ARMTemplates/Readme.md index 938ebfb1..417f8e18 100644 --- a/ARMTemplates/Readme.md +++ b/ARMTemplates/Readme.md @@ -1 +1,4 @@ -ARM Templates +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](../ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +We are including ARM templates for various resources which can be used as reference when creating your own templates. These 'compliant' templates have been created after passing applicable AzSK controls for corresponding resources. Looking forward to early adopters/feedback. diff --git a/ARMTemplates/SQLDatabase.json b/ARMTemplates/SQLDatabase.json index 5cfda2ae..e96b3c38 100644 --- a/ARMTemplates/SQLDatabase.json +++ b/ARMTemplates/SQLDatabase.json @@ -68,6 +68,7 @@ }, "emailAddresses": { "type": "string", + "defaultValue": "user@contoso.com", "metadata": { "description": "Email address for alerts." } diff --git a/ARMTemplates/ServiceBus.json b/ARMTemplates/ServiceBus.json index d0cd5b7c..9cdc3bd4 100644 --- a/ARMTemplates/ServiceBus.json +++ b/ARMTemplates/ServiceBus.json @@ -19,7 +19,7 @@ "metadata": { "description": "Name of the Storage account for storing logs" } - }, + } }, "variables": { "sbVersion": "2015-08-01" @@ -90,11 +90,8 @@ ] } } - - - ] } ], "outputs": {} -} \ No newline at end of file +} diff --git a/ARMTemplates/StorageTemplate.json b/ARMTemplates/StorageTemplate.json index 1f5a9c7f..85e0c627 100644 --- a/ARMTemplates/StorageTemplate.json +++ b/ARMTemplates/StorageTemplate.json @@ -158,10 +158,10 @@ "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageaccount'))]" ] }, - { + { "type": "Microsoft.Storage/storageAccounts", "sku": { - "name": "Standard_GRS",//[Azure_Storage_Deploy_Use_Geo_Redundant] + "name": "Standard_GRS", //[Azure_Storage_Deploy_Use_Geo_Redundant] **This control has been deprecated** "tier": "Standard" }, "kind": "Storage", @@ -170,17 +170,21 @@ "location": "southcentralus", "tags": {}, "properties": { - "encryption": { - "keySource": "Microsoft.Storage", - "services": { - "blob": { - "enabled": true//[Azure_Storage_DP_Encrypt_At_Rest_Blob] + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": { + "enabled": true //[Azure_Storage_DP_Encrypt_At_Rest_Blob] **This control has been deprecated** + + }, + "file": { + "enabled": true //[Azure_Storage_DP_Encrypt_At_Rest_File] **This control has been deprecated** + } } - } + }, + "supportsHttpsTrafficOnly": true //[Azure_Storage_DP_Encrypt_In_Transit] }, - "supportsHttpsTrafficOnly": true //[Azure_Storage_DP_Encrypt_In_Transit] - }, "dependsOn": [] } ] -} \ No newline at end of file +} diff --git a/ARMTemplates/VirtualMachine.json b/ARMTemplates/VirtualMachine.json index c2361fdd..b2147b9e 100644 --- a/ARMTemplates/VirtualMachine.json +++ b/ARMTemplates/VirtualMachine.json @@ -109,7 +109,8 @@ "apiVersion": "2015-06-15", "location": "[resourceGroup().location]", "properties": { - "accountType": "[variables('storageAccountType')]" + "accountType": "[variables('storageAccountType')]", + "supportsHttpsTrafficOnly": true //[Azure_Storage_DP_Encrypt_In_Transit] } }, { @@ -161,6 +162,7 @@ "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]" ], "properties": { + "enableIPForwarding": false, "ipConfigurations": [ { "name": "ipconfig1", @@ -182,6 +184,9 @@ "type": "Microsoft.Compute/virtualMachines", "name": "[parameters('vmName')]", "location": "[resourceGroup().location]", + "identity": { + "type": "SystemAssigned" + }, "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]", "[concat('Microsoft.Network/networkInterfaces/', parameters('nicName'))]" @@ -285,6 +290,22 @@ "protectedSettings": null } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", //Azure_VirtualMachine_SI_Deploy_GuestConfig_Extension + "name": "[concat(parameters('vmName'), '/GuestConfigForWindows')]", + "location": "[resourceGroup().location]", + "apiVersion": "2015-05-01-preview", + "dependsOn": [ + "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]" + ], + "properties": { + "publisher": "Microsoft.GuestConfiguration", + "type": "ConfigurationForWindows", + "typeHandlerVersion": "1.11", + "autoUpgradeMinorVersion": true + } + } ] } \ No newline at end of file diff --git a/ARMTemplates/api-management-service-in-internal-vnet.json b/ARMTemplates/api-management-service-in-internal-vnet.json new file mode 100644 index 00000000..c1f32ce8 --- /dev/null +++ b/ARMTemplates/api-management-service-in-internal-vnet.json @@ -0,0 +1,373 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "apiManagementServiceName": { + "type": "string", + "metadata": { + "description": "Name of the API Management service." + } + }, + "publisherEmail": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "The email address of the owner of the service" + } + }, + "publisherName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "The name of the owner of the service" + } + }, + "sku": { + "type": "string", + "allowedValues": [ + "Developer", + "Standard", + "Premium" + ], + "metadata": { + "description": "The pricing tier of this API Management service" + } + }, + "skuCount": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "The instance size of this API Management service." + } + }, + "virtualNetworkName": { + "type": "string", + "metadata": { + "description": "Virtual Network name" + } + }, + "virtualNetworkAddressPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/16", + "metadata": { + "description": "Address prefix" + } + }, + "subnetPrefix": { + "type": "string", + "defaultValue": "10.0.0.0/24", + "metadata": { + "description": "Subnet Prefix" + } + }, + "subnetName": { + "type": "string", + "metadata": { + "description": "Subnet Name" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "variables": { + "subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnetName'))]", + "apimNsgName": "[concat('apimnsg', uniqueString(resourceGroup().id))]" + }, + "resources": [ + { + "type": "Microsoft.Network/networkSecurityGroups", + "name": "[variables('apimNsgName')]", + "apiVersion": "2018-10-01", + "location": "[parameters('location')]", + "properties": { + "securityRules": [ + { + "name": "Client_communication_to_API_Management", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "80", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + { + "name": "Secure_Client_communication_to_API_Management", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 110, + "direction": "Inbound" + } + }, + { + "name": "Management_endpoint_for_Azure_portal_and_Powershell", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "3443", + "sourceAddressPrefix": "ApiManagement", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 120, + "direction": "Inbound" + } + }, + { + "name": "Dependency_on_Redis_Cache", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "6381-6383", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 130, + "direction": "Inbound" + } + }, + { + "name": "Dependency_on_Azure_SQL", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "1433", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Sql", + "access": "Allow", + "priority": 140, + "direction": "Outbound" + } + }, + { + "name": "Dependency_for_Log_to_event_Hub_policy", + "properties": { + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "5671", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "EventHub", + "access": "Allow", + "priority": 150, + "direction": "Outbound" + } + }, + { + "name": "Dependency_on_Redis_Cache_outbound", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "6381-6383", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 160, + "direction": "Outbound" + } + }, + { + "name": "Dependency_on_Azure_File_Share_for_GIT", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "445", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Storage", + "access": "Allow", + "priority": 170, + "direction": "Outbound" + } + }, + { + "name": "Azure_Infrastructure_Load_Balancer", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "AzureLoadBalancer", + "destinationAddressPrefix": "VirtualNetwork", + "access": "Allow", + "priority": 180, + "direction": "Inbound" + } + }, + { + "name": "Publish_DiagnosticLogs_And_Metrics", + "properties": { + "description": "APIM Logs and Metrics for consumption by admins and your IT team are all part of the management plane", + "protocol": "Tcp", + "sourcePortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "AzureMonitor", + "access": "Allow", + "priority": 185, + "direction": "Outbound", + "destinationPortRanges": [ + "443", + "12000", + "1886" + ] + } + }, + { + "name": "Connect_To_SMTP_Relay_For_SendingEmails", + "properties": { + "description": "APIM features the ability to generate email traffic as part of the data plane and the management plane", + "protocol": "Tcp", + "sourcePortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Internet", + "access": "Allow", + "priority": 190, + "direction": "Outbound", + "destinationPortRanges": [ + "25", + "587", + "25028" + ] + } + }, + { + "name": "Authenticate_To_Azure_Active_Directory", + "properties": { + "description": "Connect to Azure Active Directory for Developer Portal Authentication or for Oauth2 flow during any Proxy Authentication", + "protocol": "Tcp", + "sourcePortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "AzureActiveDirectory", + "access": "Allow", + "priority": 200, + "direction": "Outbound", + "destinationPortRanges": [ + "80", + "443" + ] + } + }, + { + "name": "Dependency_on_Azure_Storage", + "properties": { + "description": "APIM service dependency on Azure Blob and Azure Table Storage", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Storage", + "access": "Allow", + "priority": 100, + "direction": "Outbound" + } + }, + { + "name": "Publish_Monitoring_Logs", + "properties": { + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "AzureCloud", + "access": "Allow", + "priority": 300, + "direction": "Outbound" + } + }, + { + "name": "Deny_All_Internet_Outbound", + "properties": { + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "*", + "sourceAddressPrefix": "VirtualNetwork", + "destinationAddressPrefix": "Internet", + "access": "Deny", + "priority": 999, + "direction": "Outbound" + } + } + ] + }, + "dependsOn": [] + }, + { + "apiVersion": "2018-10-01", + "type": "Microsoft.Network/virtualNetworks", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', variables('apimNsgName'))]" + ], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('virtualNetworkAddressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnetName')]", + "properties": { + "addressPrefix": "[parameters('subnetPrefix')]", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('apimNsgName'))]" + } + } + } + ] + } + }, + { + "apiVersion": "2018-01-01", + "name": "[parameters('apiManagementServiceName')]", + "type": "Microsoft.ApiManagement/service", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]" + ], + "sku": { + "name": "[parameters('sku')]", + "capacity": "[parameters('skuCount')]" + }, + "properties": { + "publisherEmail": "[parameters('publisherEmail')]", + "publisherName": "[parameters('publisherName')]", + "virtualNetworkType": "Internal", + "virtualNetworkConfiguration": { + "subnetResourceId": "[variables('subnetRef')]" + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "type": "Microsoft.ApiManagement/service/apis", + "apiVersion": "2019-01-01", + "name": "[concat(parameters('apiManagementServiceName'), '/echo-api')]", + "dependsOn": [ + "[resourceId('Microsoft.ApiManagement/service', parameters('apiManagementServiceName'))]" + ], + "properties": { + "displayName": "Echo API", + "apiRevision": "1", + "serviceUrl": "http://echoapi.cloudapp.net/api", + "path": "echo", + "protocols": [ + "https" + ], + "isCurrent": true + } + } + ] +} \ No newline at end of file diff --git a/Archive/Migration.md b/Archive/Migration.md new file mode 100644 index 00000000..bda7360e --- /dev/null +++ b/Archive/Migration.md @@ -0,0 +1,180 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](/ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +## Migrating from 'AzSDK' to 'AzSK' + +

    IMPORTANT:

    + +> 1) If you are from Microsoft CSE&O, please use the steps [here](https://aka.ms/devopskit/migration). +> **Do not** use the migration instructions on this page. These are for non-MS consumers of the DevOps Kit. +> 2) If you are external to Microsoft, then the steps required to migrate to AzSK depend upon whether subscriptions in your org are running with the generic (org-neutral) policy or you have setup a custom AzSDK policy for your organization using the [`Install-AzSDKOrganizationPolicy`](https://github.com/azsdk/azsdk-docs/tree/master/07-Customizing-AzSDK-for-your-Org) command. +> These two steps are described below. The first step guides you for migrating org policy and the second step guides individual subscription owners for migrating from 'AzSDK' to 'AzSK'. + +### Step-1: Migrating Org Policy: +> **Note:** Step-1 is required only if you have [custom org policy](../07-Customizing-AzSK-for-your-Org/Readme.md) setup (as mentioned above). If not, then directly go to Step-2 further below. +> +> Also, if your org policy setup is basic/trivial to replicate, you might consider recreating a fresh setup using the Install-AzSKOrganizationPolicy cmdlet. In either case, individual subscription owners in your org should not migrate their subscriptions before org policy has been migrated. (That is, only after you have completed Step-1 should individual subscription owners complete Step-2.) +> +> If you would like to understand how policy and subscription migration works under the hood, please review the policy migration question in the FAQ below. + + +[Pre-Requisite: You must be an **Owner** for the subscription where your org policy is hosted.) + + 0) Close all PS sessions. + + 1) Open a *fresh* PS session and install the latest DevOps Kit release by running the command below: (This will get + the new 'AzSK' module onto your machine.) + + ```PowerShell + install-module AzSK -Scope CurrentUser -AllowClobber + ``` + + 2) Close the installation session, open a *fresh* PS session again and run the following commands: (This will migrate org-policy and create new resources as per 'AzSK' module.) + + The OrgName and DepartmentName values in the command below should be the same ones you used when setting up org policy using AzSDK earlier. + + ```PowerShell + import-module AzSK + Update-AzSKOrganizationPolicy -SubscriptionId -OrgName -DepartmentName -Migrate + ``` + + **Note:** + - If you have made any changes/customizations to `AzSDK-EasyInstaller.ps1` or `RunbookScanAgent.ps1` (e.g., if you changed the default flags used while running CA scan commands) then you should re-apply those to the newly generated `AzSK-EasyInstaller.ps1` and `RunbookScanAgent.ps1` respectively. + - If you are using baseline control feature, you should should add -UseBaselineControls flag for commands Get-AzSKAzureServicesSecurityStatus and Get-AzSKSubscriptionSecurityStatus in `RunbookScanAgent.ps1` file. + + +At this point, policy migration is complete. However, we will do some additional verifications to ensure that it worked successfully before notifying individual subscription owners to migrate. + +3) Run the newly generated **"iwr"** command which was displayed in the output of the migration command above. (This is basically the *new* installation command for your org created using AzSK-based policy containers.) + + ```PowerShell + # Note: replace the 'iwr' line below with the post-migrate 'iwr' for your org as output by the previous step + iwr 'https://azsk............/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex + ``` + + 4) Now start another *fresh* PS session and verify if the newly setup policy settings are in effect. You can do so by running AzSK scan commands such as GSS (Get-Az**SK**SubscriptionSecurityStatus) or GRS (Get-Az**SK**AzureServicesSecurityStatus) for any of your subscriptions. (If you have configured a custom controls baseline, you can also specify '-UseBaselineControls' flag to validate that your org-specific baseline is honored by the scan commands post-migration.) + + 5) You can now communicate the newly generated **"iwr"** to your subscription owners/end users so that they can install the new Az**SK** module using the latest (migrated) org policy. After installing using the new **"iwr"** all subscription owners can migrate their subscriptions to "AzSK" using instructions from Step-2 below. + +**Notes:** + - Your old (AzSDK-based) org policy will be retained under the old "AzSDK-[OrgName]-[DeptName]-RG" resource group inside your policy host subscription. You can delete this RG after ensuring that migration has worked as expected for both the policy and individual subscriptions across your org. + + - If you had enabled 'baseline scanning' via the "SupportedSources = "CC"" setting in ControlSettings.json, that approach has been deprecated. Please use the "-UseBaselineControls" switch directly in the command invocation inside you RunbookScanAgent.PS1. + + - If you had made changes to CosmosDB settings and had an entry for 'cosmosdb.json' in your ServerConfigMetadata.json file, you may have to rename the file to 'CosmosDB.json' and re-upload it. + + - Please review different configuration capabilities available for org policy control in the org policy section [here](../07-Customizing-AzSK-for-your-Org/Readme.md#basic-files-setup-during-policy-setup). + +
    + +### Step-2: Migrating individual subscriptions: +The steps below will help you to migrate your subscription from 'AzSDK' to 'AzSK'. + +[Pre-requisite: You should be an **Owner** for the subscription being migrated.] + + 0) Close all PS sessions. + + 1) Open a *fresh* PS session and install the latest release by running **one** of the 2 commands below (this will get + the new 'AzSK' module onto your machine): + + ```PowerShell + # Run this command if you do not have org-policy setup + install-module AzSK -Scope CurrentUser -AllowClobber + + # Run this command if your organization has custom org-policy setup. (The exact command in this case will be provided by your organization's cloud security team.) + iwr 'https://azsk............/AzSK-EasyInstaller.ps1' -UseBasicParsing | iex + ``` + 2) Close the installation session, open a *fresh* PS session again and run the following: + + ```PowerShell + import-module AzSK + Update-AzSKSubscriptionSecurity -SubscriptionId -Migrate + ``` + +This will make all changes necessary in your subscription in order to start using the new ('AzSK') module. +If any of the individual steps fail, you can retry migration simply by re-running the 'migrate' command +as per (2) above. + +For other questions related to migration (e.g., *Why are we migrating? What happens behind the scenes during +migration? What about CICD?* etc., please see the FAQ at the end of this page. + +**Note:** Until a subscription is migrated, you may be able to use the 'AzSDK' module and corresponding 'AzSDK' +versions of cmdlets as earlier. +However, after a subscription has been migrated, new 'AzSK' versions of the cmdlets +from the new module should only be used. If you are using generic org-policy (i.e., you do not have a custom org policy and an "iwr-based" setup), you may need to explicitly uninstall the old (AzSDK) module using `uninstall-module AzSDK -Force` from a fresh PS console after closing other existing PS sessions. + +The logs generated by locally run scan commands from the new module will appear +under the `'%localappdata%\Microsoft\AzSKLogs'` folder. + + +#### FAQ: + +##### Why are we migrating from AzSDK to AzSK? +We received feedback from various forums that the 'SDK' in the module name was misleading because 'SDK' is +traditionally used for 'Software Development Kit'. Secondly, some folks were also confusing 'AzSDK' and 'Azure SDK' +using the two interchangeably. + + +##### What exactly happens during migration? +The migration process basically prepares your local machine and your subscription to start using the new +'AzSK' PS module. Depending on the subscription security features from the DevOps Kit you have setup on your +subscription, the following steps happen during migration: + + - The old resource group ('AzSDKRG') will be retained for certain duration and locked for any modifications post migration + - Attestation data/ Resource groups tags are auto migrated to the new resource group ('AzSKRG') + - Attestation data is still retained in the old storage account as backup + - Previously setup alerts, ARM policies and Continuous Assurance Automation Account will get deleted + and corresponding new resources will get created under AzSK RG. + +If you created any other resources under the (old) DevOps Kit resource group ('AzSDKRG') you may need to migrate +them yourselves. + +##### How will the old cmdlets (from the old 'AzSDK' module) behave? +If you have not yet migrated, all AzSDK cmdlets (Get-AzSDKxxx or Set-AzSDKxxx) will work as usual. The latest +version of AzSDK (2.11.x) will show warnings about migration. + +Once you migrate your subscription, most cmdlets from AzSDK 2.11.x will report errors telling you to use +cmdlets from the 'AzSK' module. + +##### Can I use the new 'AzSK' module if I have not migrated? +Some commands (which are 'read only' in behavior) will work. However, others (e.g., attestation or Set-AzSKSubscriptionSecurity) +will be blocked. This is to not create conflicts with 'AzSDK-based' state in the subscription. + +##### How will Continuous Assurance transition through migration? +If you have not yet migrated, the current AzSDK setup will seamlessly transition by updating the AzSDK module +to the latest AzSDK (version 2.11.x). Thus existing CA setups will not get impacted (scanning will continue as earlier). + +Once you migrate, the migration process will create a new CA setup in the subscription using the same settings +that were provided when CA was setup originally. The new CA setup will be 'AzSK'-based and will import the 'AzSK' +module into the automation account. Thereafter, CA scanning will use 'AzSK' and will update to newer releases of +'AzSK' module whenever they become available. + +##### What about CICD extension? +The CICD extension has been revised to reflect the switch from 'AzSDK' to 'AzSK'. +The previous extension will continue to work in the pipeline. Once a subscription has been migrated, you should +just go to the extension UI and select the newest version. + +If you have setup CICD in non-hosted mode, you may have to manually remove the older module as an additional step. + +##### Are my old CA scan logs retained after migration? +Yes. We retain the old CA logs in the (old) storage account within 'AzSDKRG'. The migration process places a 'read' +lock on 'AzSDKRG'. Because of this, you may not be able to migrate to the storage account's blobs and view the logs. +Should you need to view any of the old logs, you can go to the 'AzSDK' resource group and view 'Locks' for it. +Change the lock type from 'read-only' to 'delete' temporarily and download/view and logs you wish to. However, as soon +as you can, please change the lock type back to 'read only'. This lock required so that other users using older 'AzSDK' +modules (prior to AzSDK 2.11.x) should not be able to write to the old RG once migration has been performed. + +##### What happens during 'org policy' migration? +(This applies only if you have custom org policy setup.) + +If you setup custom org policy using the Install-AzSDKOrganizationPolicy cmdlet in the past, you perhaps know that your customized org policy is hosted in your (master) subscription within a resource group named after your org and department name. Individual subscription owners across your org setup the DevOps Kit using an **"iwr"**-based installer that is customized for your org. This ensures that all users in the org run the DevOps Kit cmdlets using policy from a central policy store that is owned and managed by you. + +In order to migrate policy, as the owner of the policy host subscription, you need to run the policy migration command. Behind the scenes, the policy migration occurs using the following steps: + + a) The migration command first downloads all artifacts from the current policy store onto a folder on your desktop with the name 'AzSK-[OrgName]-[DeptName]-Policy'. + + b) It then creates new resources with 'AzSK'-based names in the policy host subscription + + c) Finally, the old policy JSONs and other files are fetched from the local copy (on the desktop) and uploaded to the new policy location. + + d) A new **"iwr"** command is generated for use by subscription owners to install 'AzSK' with policy URL pointing to the new location. diff --git a/Blogs/Blog1.md b/Blogs/Blog1.md index b6391364..9be6aa91 100644 --- a/Blogs/Blog1.md +++ b/Blogs/Blog1.md @@ -1,3 +1,6 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](/ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + Blog ======================================= diff --git a/FAQs/Readme.md b/FAQs/Readme.md index c56f7677..f922a49c 100644 --- a/FAQs/Readme.md +++ b/FAQs/Readme.md @@ -1,16 +1,27 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](/ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # FAQs - ### Setup - [Should I run PowerShell ISE as administrator or regular user?](../00a-Setup/Readme.md#should-i-run-powershell-ise-as-administrator-or-regular-user) - [Error message: "Running scripts is disabled on this system..."](../00a-Setup/Readme.md#error-message-running-scripts-is-disabled-on-this-system) - [Error message: "PackageManagement\Install-Package: cannot process argument transformation on parameter 'InstalledModuleInfo'..."](../00a-Setup/Readme.md#error-message-packagemanagementinstall-package-cannot-process-argument-transformation-on-parameter-installedmoduleinfo) - - [Error message: "WARNING: The version '3.x.y' of module 'AzureRM.Profile' is currently in use. Retry the operation after closing..."](../00a-Setup/Readme.md#error-message-warning-the-version-3xy-of-module-azurermprofile-is-currently-in-use-retry-the-operation-after-closing) + - [Error message: "WARNING: The version '1.x.y' of module 'Az.Accounts' is currently in use. Retry the operation after closing..."](../00a-Setup/Readme.md#error-message-warning-the-version-1xy-of-module-azaccounts-is-currently-in-use-retry-the-operation-after-closing) - [Error message: "The property 'Id' cannot be found on this object. Verify that the property exists..."](../00a-Setup/Readme.md#error-message-the-property-id-cannot-be-found-on-this-object-verify-that-the-property-exists) - [Message: "Warning : Microsoft Azure PowerShell collects data about how users use PowerShell cmdlets..."](../00a-Setup/Readme.md#message-warning--microsoft-azure-powershell-collects-data-about-how-users-use-powershell-cmdlets) + - [When will AzSK support the newest Az dependencies? Can I run both side by side? In the meantime, what if I need to run both AzSK and the new version of Az modules (for different tasks)?](../00a-Setup/Readme.md#when-will-azsk-support-the-newest-az-dependencies-can-i-run-both-side-by-side-in-the-meantime-what-if-i-need-to-run-both-azsk-and-the-new-version-of-az-modules-for-different-tasks) + - [How often should I upgrade my installation of AzSK? How long will it take?](../00a-Setup/Readme.md#how-often-should-i-upgrade-my-installation-of-azsk-how-long-will-it-take) - ### Subscription-Security - #### AzSK: Subscription Security Provisioning - [Is it possible to setup an individual feature (e.g., just alerts or just ARM Policy)?](../01-Subscription-Security/Readme.md#is-it-possible-to-setup-an-individual-feature-eg-just-alerts-or-just-arm-policy) + + - [Set-AzSKSubscriptionSecurity or Set-AzSKAzureSecurityCenterPolicies returns - InvalidOperation: The remote server returned an error: (500) Internal Server Error?](../01-Subscription-Security/Readme.md#set-azsksubscriptionsecurity--or-set-azskazuresecuritycenterpolicies-returns---invalidoperation-the-remote-server-returned-an-error-500-internal-server-error) + + - #### AzSK: Subscription Activity Alerts - [Can I get the alert emails to go to a distribution group instead of an individual email id?](../01-Subscription-Security/Readme.md#can-i-get-the-alert-emails-to-go-to-a-distribution-group-instead-of-an-individual-email-id) - [How can I find out more once I receive an alert email?](../01-Subscription-Security/Readme.md#how-can-i-find-out-more-once-i-receive-an-alert-email) @@ -19,6 +30,7 @@ - [What happens if an action in the subscription violates the policy?](../01-Subscription-Security/Readme.md#what-happens-if-an-action-in-the-subscription-violates-the-policy) - [Which ARM policies are installed by the setup script?](../01-Subscription-Security/Readme.md#which-arm-policies-are-installed-by-the-setup-script) - [How can I check for policy violations?](../01-Subscription-Security/Readme.md#how-can-i-check-for-policy-violations) + - [Are there more policies available for use?](../01-Subscription-Security/Readme.md#are-there-more-policies-available-for-use) - ### Secure Development - #### Security Verification Tests (SVT) @@ -26,23 +38,53 @@ - [What do the different columns in the status report mean?](../02-Secure-Development/Readme.md#what-do-the-different-columns-in-the-status-report-mean) - [How can I find out what to do for controls that are marked as 'manual'?](../02-Secure-Development/Readme.md#how-can-i-find-out-what-to-do-for-controls-that-are-marked-as-manual) - [How can I implement fixes for the failed ones which have no auto-fix available?](../02-Secure-Development/Readme.md#how-can-i-implement-fixes-for-the-failed-ones-which-have-no-auto-fix-available) + - [What are Owner access controls? Why can't those be run via CA and need to be run manually?

    (Or)

    I have setup AzSK Continuous Assurance on my subscription. Do I still need to run the scans locally?

    Description:
    Running the scan locally for all the resources in the subscription is time consuming. Do I still need to run that even though I have already setup Continuous Assurance on my subscription?](../02-Secure-Development/Readme.md#what-are-owner-access-controls-why-cant-those-be-run-via-ca-and-need-to-be-run-manually---or--i-have-setup-azsk-continuous-assurance-on-my-subscription-do-i-still-need-to-run-the-scans-locally---description--running-the-scan-locally-for-all-the-resources-in-the-subscription-is-time-consuming-do-i-still-need-to-run-that-even-though-i-have-already-setup-continuous-assurance-on-my-subscription) - ### Security-In-CICD - #### Security Verification Tests (SVTs) in VSTS pipeline - [I have enabled AzSK_SVTs task in my release pipeline. I am getting an error ‘The specified module 'AzSK' was not loaded because no valid module file was found in any module directory’. How do I resolve this issue?](../03-Security-In-CICD/Readme.md#i-have-enabled-AzSK_svts-task-in-my-release-pipeline-i-am-getting-an-error-the-specified-module-AzSK-was-not-loaded-because-no-valid-module-file-was-found-in-any-module-directory-how-do-i-resolve-this-issue) - [I have enabled AzSK_SVTs task in my release pipeline. It is taking too much time every time I queue a release, how can I reduce that time?](../03-Security-In-CICD/Readme.md#i-have-enabled-AzSK_svts-task-in-my-release-pipeline-it-is-taking-too-much-time-every-time-i-queue-a-release-how-can-i-reduce-that-time) + - [Why AzSK_SVTs task in my release pipeline has suddenly started failing 'Verify'/'Manual'/'Remediate'/'Exception' controls?](../03-Security-In-CICD/Readme.md#why-azsk_svts-task-in-my-release-pipeline-has-suddenly-started-failing-verifymanualremediateexception-controls) + - [I want to run AzSK_SVT on non-hosted agent. What are the pre-requisites for running AzSK_SVTs task on non-hosted agent?](../03-Security-In-CICD/Readme.md#i-want-to-run-azsk_svt-on-non-hosted-agent-what-are-the-pre-requisites-for-running-azsk_svts-task-on-non-hosted-agent) + - [Why attestation is not getting respected in AzSK_SVT task in CICD pipeline?](../03-Security-In-CICD/Readme.md#why-attestation-is-not-getting-respected-in-azsk_svt-task-in-cicd-pipeline) - ### Continuous Assurance (CA) - #### Baseline Continuous Assurance - [What permission do I need to setup CA?](../04-Continous-Assurance/Readme.md#what-permission-do-i-need-to-setup-ca) - - [Is it possible to setup CA if there is no OMS workspace?](../04-Continous-Assurance/Readme.md#is-it-possible-to-setup-ca-if-there-is-no-oms-workspace) - - [Which OMS workspace should I use for my team when setting up CA?](../04-Continous-Assurance/Readme.md#which-oms-workspace-should-i-use-for-my-team-when-setting-up-ca) + - [Is it possible to setup CA if there is no Log Analytics workspace?](../04-Continous-Assurance/Readme.md#is-it-possible-to-setup-ca-if-there-is-no-log-analytics-workspace) + - [Which Log Analytics workspace should I use for my team when setting up CA?](../04-Continous-Assurance/Readme.md#which-log-analytics-workspace-should-i-use-for-my-team-when-setting-up-ca) - [Why does CA setup ask for resource groups?](../04-Continous-Assurance/Readme.md#why-does-ca-setup-ask-for-resource-groups) - [How can I find out if CA was previously setup in my subscription?](../04-Continous-Assurance/Readme.md#how-can-i-find-out-if-ca-was-previously-setup-in-my-subscription) - [How can I tell that my CA setup has worked correctly?](../04-Continous-Assurance/Readme.md#how-can-i-tell-that-my-ca-setup-has-worked-correctly) - [Is providing resource groups mandatory?](../04-Continous-Assurance/Readme.md#is-providing-resource-groups-mandatory) - [What if I need to change the resource groups after a few weeks?](../04-Continous-Assurance/Readme.md#what-if-i-need-to-change-the-resource-groups-after-a-few-weeks) - - [Do I need to also setup AzSK OMS solution?](../04-Continous-Assurance/Readme.md#do-i-need-to-also-setup-AzSK-oms-solution) - - [How much does it cost to setup Continuous Assurance alongwith OMS monitoring solution?](../04-Continous-Assurance/Readme.md#how-much-does-it-cost-to-setup-continuous-assurance-alongwith-oms-monitoring-solution) + - [Do I need to also setup AzSK Monitoring solution?](../04-Continous-Assurance/Readme.md#do-i-need-to-also-setup-azsk-monitoring-solution) + - [How much does it cost to setup Continuous Assurance along with the monitoring solution?](../04-Continous-Assurance/Readme.md#how-much-does-it-cost-to-setup-continuous-assurance-along-with-the-monitoring-solution) + - [What are AzSKRG and AzSK_CA_SPN used for?](../04-Continous-Assurance/Readme.md#what-are-azskrg-and-azsk_ca_spn-used-for) + - [How to fix SPN permissions for my AzSK Continuous Assurance setup?](../04-Continous-Assurance/Readme.md#how-to-fix-spn-permissions-for-my-azsk-continuous-assurance-setup) + - [How to renew the certificate used for Continuous Assurance?](../04-Continous-Assurance/Readme.md#how-to-renew-the-certificate-used-for-continuous-assurance) + - [What are some example controls that are not scanned by CA?](../04-Continous-Assurance/Readme.md#what-are-some-example-controls-that-are-not-scanned-by-ca) + - [Should I manually update modules in the AzSK CA automation account?](../04-Continous-Assurance/Readme.md#should-i-manually-update-modules-in-the-azsk-ca-automation-account) + - [Difference between scanned controls from CA v. ad hoc scans](../04-Continous-Assurance/Readme.md#difference-between-scanned-controls-from-ca-v-ad-hoc-scans) - +- ### Addressing Control Failures + - [Can fixing an AzSK control impact my application?](../00c-Addressing-Control-Failures/Readme.md#can-fixing-an-azsk-control-impact-my-application) + - [What permission should I have to perform attestation in AzSK?](../00c-Addressing-Control-Failures/Readme.md#what-permission-should-i-have-to-perform-attestation-in-azsk) + - [Attestation fails with permission error even though I am Owner.](../00c-Addressing-Control-Failures/Readme.md#attestation-fails-with-permission-error-even-though-i-am-owner) + - [Why do I have new control failures from AzSK?](../00c-Addressing-Control-Failures/Readme.md#why-do-i-have-new-control-failures-from-azsk) + - [I am trying to enable diagnostic logs using the recommendation command 'Set-AzDiagnosticSetting' given in the AzSK control. But the command fails with error 'The diagnostic setting 'service' doesn't exist'. How do I resolve this error?](../00c-Addressing-Control-Failures/Readme.md#i-am-trying-to-enable-diagnostic-logs-using-the-recommendation-command-set-azurermdiagnosticsetting-given-in-the-azsk-control-but-the-command-fails-with-error-the-diagnostic-setting-service-doesnt-exist-how-do-i-resolve-this-error) + - [I wish to deploy virtual networking in a hub and spoke architecture, where ExpressRoute is connected to a Core network, which is then connected via VNET Peering, or VPN to other VNET’s, or other Azure datacentres. But some of the controls regarding ExpressRoute-connected Virtual Networks contradict my requirement. How does AzSK justify the controls like "There should not be another virtual network gateway (GatewayType = Vpn) in an ER-vNet" and "There should not be any virtual network peerings on an ER-vNet"? How should I satisfy them without changing my implementation plans?](../00c-Addressing-Control-Failures#i-wish-to-deploy-virtual-networking-in-a-hub-and-spoke-architecture-where-expressroute-is-connected-to-a-core-network-which-is-then-connected-via-vnet-peering-or-vpn-to-other-vnets-or-other-azure-datacentres-but-some-of-the-controls-regarding-expressroute-connected-virtual-networks-contradict-my-requirement-how-does-azsk-justify-the-controls-like-there-should-not-be-another-virtual-network-gateway-gatewaytype--vpn-in-an-er-vnet-and-there-should-not-be-any-virtual-network-peerings-on-an-er-vnet-how-should-i-satisfy-them-without-changing-my-implementation-plans) + - [I am unable to scan/attest API connection controls independently. I am getting the error: Could not find any resources to scan under Resource Group. InvalidOperation: Could not find any resources that match the specified criteria. How should I scan and bulk attest API connection controls?](../00c-Addressing-Control-Failures/Readme.md#i-am-unable-to-scanattest-api-connection-controls-independently-i-am-getting-the-error-could-not-find-any-resources-to-scan-under-resource-group-invalidoperation-could-not-find-any-resources-that-match-the-specified-criteria-how-should-i-scan-and-bulk-attest-api-connection-controls) + - [I cannot find the API connection on portal that is listed in the AzSK CSV scan result. Where can I find these resource on portal?](../00c-Addressing-Control-Failures/Readme.md#i-cannot-find-the-api-connection-on-portal-that-is-listed-in-the-azsk-csv-scan-result-where-can-i-find-these-resource-on-portal) + - [How do I remediate failing control Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG?](../00c-Addressing-Control-Failures/Readme.md#how-do-i-remediate-failing-control-azure_subscription_authz_dont_grant_persistent_access_rg) + - [How do I remediate failing control Azure_APIManagement_DP_Use_Secure_TLS_Version?](../00c-Addressing-Control-Failures/Readme.md#how-do-i-remediate-failing-control-azure_apimanagement_dp_use_secure_tls_version) + - [How do I remediate failing control Azure_AppService_DP_Use_Secure_TLS_Version?](../00c-Addressing-Control-Failures/Readme.md#how-do-i-remediate-failing-control-azure_appservice_dp_use_secure_tls_version) + - [Many of the Azure Databricks control goes to manual state from both CA and local scan. What should I do to evaluate Azure Databricks resources properly?](../00c-Addressing-Control-Failures/Readme.md#many-of-the-azure-databricks-control-goes-to-manual-state-from-both-ca-and-local-scan-what-should-i-do-to-evaluate-azure-databricks-resources-properly) + + +- ### Org Policy + - [I am getting exception "DevOps Kit was configured to run with '***' policy for this subscription. However, the current command is using 'org-neutral' (generic) policy....."?](../07-Customizing-AzSK-for-your-Org/Readme.md#i-am-getting-exception-devops-kit-was-configured-to-run-with--policy-for-this-subscription-however-the-current-command-is-using-org-neutral-generic-policy-please-contact-your-organization-policy-owner-microsoftcom-for-correcting-the-policy-setup) + - [Latest AzSK is available but our Org CA are running with older version?](../07-Customizing-AzSK-for-your-Org/Readme.md#latest-azsk-is-available-but-our-org-ca-are-running-with-older-version) + - [We have configured baseline controls using ControlSettings.json on Policy Store, But Continuous Assurance (CA) is scanning all SVT controls on subscription?](../07-Customizing-AzSK-for-your-Org/Readme.md#we-have-configured-baseline-controls-using-controlsettingsjson-on-policy-store-but-continuous-assurance-ca-is-scanning-all-svt-controls-on-subscription) + - [Continuous Assurance (CA) is scanning less number of controls as compared with manual scan?](../07-Customizing-AzSK-for-your-Org/Readme.md#continuous-assurance-ca-is-scanning-less-number-of-controls-as-compared-with-manual-scan) + diff --git a/Images/01_RenewCertfromPortal.png b/Images/01_RenewCertfromPortal.png new file mode 100644 index 00000000..6a543501 Binary files /dev/null and b/Images/01_RenewCertfromPortal.png differ diff --git a/Images/02_RenewCertfromPortal.png b/Images/02_RenewCertfromPortal.png new file mode 100644 index 00000000..2c3df5a4 Binary files /dev/null and b/Images/02_RenewCertfromPortal.png differ diff --git a/Images/02_SVT_Attest_2.PNG b/Images/02_SVT_Attest_2.PNG index 0880a7b5..e8ff019f 100644 Binary files a/Images/02_SVT_Attest_2.PNG and b/Images/02_SVT_Attest_2.PNG differ diff --git a/Images/02_SVT_Attest_3.PNG b/Images/02_SVT_Attest_3.PNG index 9e344ed7..92e17a46 100644 Binary files a/Images/02_SVT_Attest_3.PNG and b/Images/02_SVT_Attest_3.PNG differ diff --git a/Images/02_SVT_Attest_4.png b/Images/02_SVT_Attest_4.png new file mode 100644 index 00000000..4164ff66 Binary files /dev/null and b/Images/02_SVT_Attest_4.png differ diff --git a/Images/02_SecIntel_VSGallery_Download.PNG b/Images/02_SecIntel_VSGallery_Download.PNG index 9bb75112..f0035a26 100644 Binary files a/Images/02_SecIntel_VSGallery_Download.PNG and b/Images/02_SecIntel_VSGallery_Download.PNG differ diff --git a/Images/02_SecIntel_VSGallery_Uninstall.PNG b/Images/02_SecIntel_VSGallery_Uninstall.PNG new file mode 100644 index 00000000..7e4c0f93 Binary files /dev/null and b/Images/02_SecIntel_VSGallery_Uninstall.PNG differ diff --git a/Images/03_ARMChecker_Logs.JPG b/Images/03_ARMChecker_Logs.JPG new file mode 100644 index 00000000..fffc8b2e Binary files /dev/null and b/Images/03_ARMChecker_Logs.JPG differ diff --git a/Images/03_Add_Build_Steps.PNG b/Images/03_Add_Build_Steps.PNG new file mode 100644 index 00000000..c14c0067 Binary files /dev/null and b/Images/03_Add_Build_Steps.PNG differ diff --git a/Images/03_Create_OMS.PNG b/Images/03_Create_OMS.PNG new file mode 100644 index 00000000..d8f4b38e Binary files /dev/null and b/Images/03_Create_OMS.PNG differ diff --git a/Images/03_Create_Release_Defination.PNG b/Images/03_Create_Release_Defination.PNG deleted file mode 100644 index 2aa4c879..00000000 Binary files a/Images/03_Create_Release_Defination.PNG and /dev/null differ diff --git a/Images/03_Create_Release_Definition.png b/Images/03_Create_Release_Definition.png new file mode 100644 index 00000000..aa9ce36e Binary files /dev/null and b/Images/03_Create_Release_Definition.png differ diff --git a/Images/03_Create_Release_Definition_ARM.JPG b/Images/03_Create_Release_Definition_ARM.JPG new file mode 100644 index 00000000..a9ce82e8 Binary files /dev/null and b/Images/03_Create_Release_Definition_ARM.JPG differ diff --git a/Images/03_Creating_Variable_Group.PNG b/Images/03_Creating_Variable_Group.PNG index 23d49ffc..8f23c96d 100644 Binary files a/Images/03_Creating_Variable_Group.PNG and b/Images/03_Creating_Variable_Group.PNG differ diff --git a/Images/03_Directly_Use_Variable.PNG b/Images/03_Directly_Use_Variable.PNG deleted file mode 100644 index f659919d..00000000 Binary files a/Images/03_Directly_Use_Variable.PNG and /dev/null differ diff --git a/Images/03_Directly_Use_Variables.png b/Images/03_Directly_Use_Variables.png new file mode 100644 index 00000000..a2670db4 Binary files /dev/null and b/Images/03_Directly_Use_Variables.png differ diff --git a/Images/03_ExcludeFiles_Param_ARMChecker.JPG b/Images/03_ExcludeFiles_Param_ARMChecker.JPG new file mode 100644 index 00000000..859e8882 Binary files /dev/null and b/Images/03_ExcludeFiles_Param_ARMChecker.JPG differ diff --git a/Images/03_FailedControl_Logs_ARMChecker.JPG b/Images/03_FailedControl_Logs_ARMChecker.JPG new file mode 100644 index 00000000..651b2cdb Binary files /dev/null and b/Images/03_FailedControl_Logs_ARMChecker.JPG differ diff --git a/Images/03_IP_Parameter_for_Task.PNG b/Images/03_IP_Parameter_for_Task.PNG deleted file mode 100644 index 431a6827..00000000 Binary files a/Images/03_IP_Parameter_for_Task.PNG and /dev/null differ diff --git a/Images/03_IP_Parameter_for_Task_ARM.JPG b/Images/03_IP_Parameter_for_Task_ARM.JPG new file mode 100644 index 00000000..7a0f0d54 Binary files /dev/null and b/Images/03_IP_Parameter_for_Task_ARM.JPG differ diff --git a/Images/03_IP_Parameters_for_Task.png b/Images/03_IP_Parameters_for_Task.png new file mode 100644 index 00000000..a9014df9 Binary files /dev/null and b/Images/03_IP_Parameters_for_Task.png differ diff --git a/Images/03_Input_Parameter.PNG b/Images/03_Input_Parameter.PNG new file mode 100644 index 00000000..c12aede3 Binary files /dev/null and b/Images/03_Input_Parameter.PNG differ diff --git a/Images/03_Install_Plugin.PNG b/Images/03_Install_Plugin.PNG new file mode 100644 index 00000000..7bf9afb1 Binary files /dev/null and b/Images/03_Install_Plugin.PNG differ diff --git a/Images/03_Issues_Release_Fail.PNG b/Images/03_Issues_Release_Fail.PNG index 22111642..f758ad2a 100644 Binary files a/Images/03_Issues_Release_Fail.PNG and b/Images/03_Issues_Release_Fail.PNG differ diff --git a/Images/03_Issues_Release_Fail_ARM.JPG b/Images/03_Issues_Release_Fail_ARM.JPG new file mode 100644 index 00000000..6e69848c Binary files /dev/null and b/Images/03_Issues_Release_Fail_ARM.JPG differ diff --git a/Images/03_Linking_To_Release.PNG b/Images/03_Linking_To_Release.PNG index 9adef9f0..66aa3b32 100644 Binary files a/Images/03_Linking_To_Release.PNG and b/Images/03_Linking_To_Release.PNG differ diff --git a/Images/03_Online_Policy_Directly_Use_Variable.PNG b/Images/03_Online_Policy_Directly_Use_Variable.PNG deleted file mode 100644 index 2578bb15..00000000 Binary files a/Images/03_Online_Policy_Directly_Use_Variable.PNG and /dev/null differ diff --git a/Images/03_Online_Policy_Directly_Use_Variables.png b/Images/03_Online_Policy_Directly_Use_Variables.png new file mode 100644 index 00000000..137cd454 Binary files /dev/null and b/Images/03_Online_Policy_Directly_Use_Variables.png differ diff --git a/Images/03_Online_Policy_Linking_Release.PNG b/Images/03_Online_Policy_Linking_Release.PNG index 94b98858..ce05c1a0 100644 Binary files a/Images/03_Online_Policy_Linking_Release.PNG and b/Images/03_Online_Policy_Linking_Release.PNG differ diff --git a/Images/03_Online_Policy_Variable_Group.PNG b/Images/03_Online_Policy_Variable_Group.PNG index 200acd4f..0d85b936 100644 Binary files a/Images/03_Online_Policy_Variable_Group.PNG and b/Images/03_Online_Policy_Variable_Group.PNG differ diff --git a/Images/03_Output_Folder.png b/Images/03_Output_Folder.png index 88ec83fa..c8392618 100644 Binary files a/Images/03_Output_Folder.png and b/Images/03_Output_Folder.png differ diff --git a/Images/03_Output_Folder_ARM.JPG b/Images/03_Output_Folder_ARM.JPG new file mode 100644 index 00000000..838ed5b6 Binary files /dev/null and b/Images/03_Output_Folder_ARM.JPG differ diff --git a/Images/03_Provide_OMS_Cred.PNG b/Images/03_Provide_OMS_Cred.PNG new file mode 100644 index 00000000..339aec53 Binary files /dev/null and b/Images/03_Provide_OMS_Cred.PNG differ diff --git a/Images/03_Release_Task.PNG b/Images/03_Release_Task.PNG index cba6aa69..54ac3578 100644 Binary files a/Images/03_Release_Task.PNG and b/Images/03_Release_Task.PNG differ diff --git a/Images/03_Release_Task_ARM.JPG b/Images/03_Release_Task_ARM.JPG new file mode 100644 index 00000000..8391c48c Binary files /dev/null and b/Images/03_Release_Task_ARM.JPG differ diff --git a/Images/03_RenewCertfromPortal.png b/Images/03_RenewCertfromPortal.png new file mode 100644 index 00000000..0aa10032 Binary files /dev/null and b/Images/03_RenewCertfromPortal.png differ diff --git a/Images/03_Save_Job.PNG b/Images/03_Save_Job.PNG new file mode 100644 index 00000000..b19a4f25 Binary files /dev/null and b/Images/03_Save_Job.PNG differ diff --git a/Images/03_Save_Release_Definition.PNG b/Images/03_Save_Release_Definition.PNG index 2127e1fa..a2670db4 100644 Binary files a/Images/03_Save_Release_Definition.PNG and b/Images/03_Save_Release_Definition.PNG differ diff --git a/Images/03_Skip_Controls_File_ARMChecker.JPG b/Images/03_Skip_Controls_File_ARMChecker.JPG new file mode 100644 index 00000000..c41a3026 Binary files /dev/null and b/Images/03_Skip_Controls_File_ARMChecker.JPG differ diff --git a/Images/03_Skip_Controls_Param_ARMCheckerJPG.JPG b/Images/03_Skip_Controls_Param_ARMCheckerJPG.JPG new file mode 100644 index 00000000..3efe61ae Binary files /dev/null and b/Images/03_Skip_Controls_Param_ARMCheckerJPG.JPG differ diff --git a/Images/03_SkippedFile_Error_ARMChecker.JPG b/Images/03_SkippedFile_Error_ARMChecker.JPG new file mode 100644 index 00000000..368df96b Binary files /dev/null and b/Images/03_SkippedFile_Error_ARMChecker.JPG differ diff --git a/Images/03_Skipped_Files_Log_ARMChecker.JPG b/Images/03_Skipped_Files_Log_ARMChecker.JPG new file mode 100644 index 00000000..90623196 Binary files /dev/null and b/Images/03_Skipped_Files_Log_ARMChecker.JPG differ diff --git a/Images/03_Start_Release_Pipeline.PNG b/Images/03_Start_Release_Pipeline.PNG index fac64a4b..12bad3aa 100644 Binary files a/Images/03_Start_Release_Pipeline.PNG and b/Images/03_Start_Release_Pipeline.PNG differ diff --git a/Images/03_Start_Release_Pipeline_ARM.JPG b/Images/03_Start_Release_Pipeline_ARM.JPG new file mode 100644 index 00000000..8fae3ef6 Binary files /dev/null and b/Images/03_Start_Release_Pipeline_ARM.JPG differ diff --git a/Images/03_Task_Catalog_ARM.JPG b/Images/03_Task_Catalog_ARM.JPG new file mode 100644 index 00000000..4e8c3d56 Binary files /dev/null and b/Images/03_Task_Catalog_ARM.JPG differ diff --git a/Images/03_Trigger_Build_1.PNG b/Images/03_Trigger_Build_1.PNG new file mode 100644 index 00000000..9d5283aa Binary files /dev/null and b/Images/03_Trigger_Build_1.PNG differ diff --git a/Images/03_Trigger_Build_2.PNG b/Images/03_Trigger_Build_2.PNG new file mode 100644 index 00000000..7c5133c6 Binary files /dev/null and b/Images/03_Trigger_Build_2.PNG differ diff --git a/Images/03_Trigger_Build_3.PNG b/Images/03_Trigger_Build_3.PNG new file mode 100644 index 00000000..50fcd8a5 Binary files /dev/null and b/Images/03_Trigger_Build_3.PNG differ diff --git a/Images/03_Upload_Plugin.PNG b/Images/03_Upload_Plugin.PNG new file mode 100644 index 00000000..fed074bf Binary files /dev/null and b/Images/03_Upload_Plugin.PNG differ diff --git a/Images/03_Use_ParamFiles_ARMCheckerJPG.jpg b/Images/03_Use_ParamFiles_ARMCheckerJPG.jpg new file mode 100644 index 00000000..2ebf5945 Binary files /dev/null and b/Images/03_Use_ParamFiles_ARMCheckerJPG.jpg differ diff --git a/Images/03_Verify_Pipeline.PNG b/Images/03_Verify_Pipeline.PNG index 7167caf8..6ffa1036 100644 Binary files a/Images/03_Verify_Pipeline.PNG and b/Images/03_Verify_Pipeline.PNG differ diff --git a/Images/03_Verify_Pipeline_ARM.JPG b/Images/03_Verify_Pipeline_ARM.JPG new file mode 100644 index 00000000..cd75e1cc Binary files /dev/null and b/Images/03_Verify_Pipeline_ARM.JPG differ diff --git a/Images/03_View_Release_OutCome.PNG b/Images/03_View_Release_OutCome.PNG index 3c7aee8d..2365b2fa 100644 Binary files a/Images/03_View_Release_OutCome.PNG and b/Images/03_View_Release_OutCome.PNG differ diff --git a/Images/03_View_Release_OutCome_ARMChecker.png b/Images/03_View_Release_OutCome_ARMChecker.png new file mode 100644 index 00000000..b18d2d6e Binary files /dev/null and b/Images/03_View_Release_OutCome_ARMChecker.png differ diff --git a/Images/04_CA_Log_Analytics.png b/Images/04_CA_Log_Analytics.png new file mode 100644 index 00000000..0a5ff277 Binary files /dev/null and b/Images/04_CA_Log_Analytics.png differ diff --git a/Images/04_CA_OMS.PNG b/Images/04_CA_OMS.PNG deleted file mode 100644 index 16ca4014..00000000 Binary files a/Images/04_CA_OMS.PNG and /dev/null differ diff --git a/Images/04_RenewCertfromPortal.png b/Images/04_RenewCertfromPortal.png new file mode 100644 index 00000000..f82b94c8 Binary files /dev/null and b/Images/04_RenewCertfromPortal.png differ diff --git a/Images/05_Application_Security_View.PNG b/Images/05_Application_Security_View.PNG deleted file mode 100644 index 0ade9094..00000000 Binary files a/Images/05_Application_Security_View.PNG and /dev/null differ diff --git a/Images/05_Application_Security_View.png b/Images/05_Application_Security_View.png new file mode 100644 index 00000000..42c68edd Binary files /dev/null and b/Images/05_Application_Security_View.png differ diff --git a/Images/05_AzSK_OMS_New_View.PNG b/Images/05_AzSK_OMS_New_View.PNG deleted file mode 100644 index 7228701e..00000000 Binary files a/Images/05_AzSK_OMS_New_View.PNG and /dev/null differ diff --git a/Images/05_Get_AzOperationalInsightsWorkspace.png b/Images/05_Get_AzOperationalInsightsWorkspace.png new file mode 100644 index 00000000..74031215 Binary files /dev/null and b/Images/05_Get_AzOperationalInsightsWorkspace.png differ diff --git a/Images/05_Get_AzureRmOperationalInsightsWorkspace.PNG b/Images/05_Get_AzureRmOperationalInsightsWorkspace.PNG deleted file mode 100644 index c3cb45aa..00000000 Binary files a/Images/05_Get_AzureRmOperationalInsightsWorkspace.PNG and /dev/null differ diff --git a/Images/05_Install-AzSKMonitoringSolution.png b/Images/05_Install-AzSKMonitoringSolution.png new file mode 100644 index 00000000..5715978d Binary files /dev/null and b/Images/05_Install-AzSKMonitoringSolution.png differ diff --git a/Images/05_Log_Analytics_Blade_RS1.PNG b/Images/05_Log_Analytics_Blade_RS1.PNG new file mode 100644 index 00000000..3fd8c9ab Binary files /dev/null and b/Images/05_Log_Analytics_Blade_RS1.PNG differ diff --git a/Images/05_Log_Analytics_Blade_RS2.PNG b/Images/05_Log_Analytics_Blade_RS2.PNG new file mode 100644 index 00000000..c5930532 Binary files /dev/null and b/Images/05_Log_Analytics_Blade_RS2.PNG differ diff --git a/Images/05_Log_Analytics_Blade_RS3.PNG b/Images/05_Log_Analytics_Blade_RS3.PNG new file mode 100644 index 00000000..ba2baa38 Binary files /dev/null and b/Images/05_Log_Analytics_Blade_RS3.PNG differ diff --git a/Images/05_Log_Analytics_Blade_RS4.PNG b/Images/05_Log_Analytics_Blade_RS4.PNG new file mode 100644 index 00000000..aa153a85 Binary files /dev/null and b/Images/05_Log_Analytics_Blade_RS4.PNG differ diff --git a/Images/05_Log_Analytics_Control_Failure.png b/Images/05_Log_Analytics_Control_Failure.png new file mode 100644 index 00000000..c9ec4b33 Binary files /dev/null and b/Images/05_Log_Analytics_Control_Failure.png differ diff --git a/Images/05_Log_Analytics_Workspace_Logs_Query.png b/Images/05_Log_Analytics_Workspace_Logs_Query.png new file mode 100644 index 00000000..e30911d0 Binary files /dev/null and b/Images/05_Log_Analytics_Workspace_Logs_Query.png differ diff --git a/Images/05_Log_Analytics_Workspace_New_View.png b/Images/05_Log_Analytics_Workspace_New_View.png new file mode 100644 index 00000000..f2fbaaf8 Binary files /dev/null and b/Images/05_Log_Analytics_Workspace_New_View.png differ diff --git a/Images/05_Log_Analytics_Workspace_Query_Duration.png b/Images/05_Log_Analytics_Workspace_Query_Duration.png new file mode 100644 index 00000000..f3b96d98 Binary files /dev/null and b/Images/05_Log_Analytics_Workspace_Query_Duration.png differ diff --git a/Images/05_Log_Analytics_Workspace_WsId_ShrKey.png b/Images/05_Log_Analytics_Workspace_WsId_ShrKey.png new file mode 100644 index 00000000..7640e3d3 Binary files /dev/null and b/Images/05_Log_Analytics_Workspace_WsId_ShrKey.png differ diff --git a/Images/05_Main_Dashboard_View.PNG b/Images/05_Main_Dashboard_View.PNG deleted file mode 100644 index 8ef4b811..00000000 Binary files a/Images/05_Main_Dashboard_View.PNG and /dev/null differ diff --git a/Images/05_OMS_Control_Failure.PNG b/Images/05_OMS_Control_Failure.PNG deleted file mode 100644 index e8fe3344..00000000 Binary files a/Images/05_OMS_Control_Failure.PNG and /dev/null differ diff --git a/Images/05_RenewCertfromPortal.png b/Images/05_RenewCertfromPortal.png new file mode 100644 index 00000000..cdf51f79 Binary files /dev/null and b/Images/05_RenewCertfromPortal.png differ diff --git a/Images/05_Setting_Log_Analytics_Workspace_App_Specific_View_Details.png b/Images/05_Setting_Log_Analytics_Workspace_App_Specific_View_Details.png new file mode 100644 index 00000000..ded01b83 Binary files /dev/null and b/Images/05_Setting_Log_Analytics_Workspace_App_Specific_View_Details.png differ diff --git a/Images/05_Setting_Log_Analytics_Workspace_Azure_Activity_Log.png b/Images/05_Setting_Log_Analytics_Workspace_Azure_Activity_Log.png new file mode 100644 index 00000000..81c0ae54 Binary files /dev/null and b/Images/05_Setting_Log_Analytics_Workspace_Azure_Activity_Log.png differ diff --git a/Images/05_Setting_Log_Analytics_Workspace_Connecting_Log_Analytics.png b/Images/05_Setting_Log_Analytics_Workspace_Connecting_Log_Analytics.png new file mode 100644 index 00000000..011f2380 Binary files /dev/null and b/Images/05_Setting_Log_Analytics_Workspace_Connecting_Log_Analytics.png differ diff --git a/Images/05_Setting_Log_Analytics_Workspace_Custom_Log.png b/Images/05_Setting_Log_Analytics_Workspace_Custom_Log.png new file mode 100644 index 00000000..e30911d0 Binary files /dev/null and b/Images/05_Setting_Log_Analytics_Workspace_Custom_Log.png differ diff --git a/Images/05_Setting_New_Log_Analytics_Workspace.png b/Images/05_Setting_New_Log_Analytics_Workspace.png new file mode 100644 index 00000000..6a38a944 Binary files /dev/null and b/Images/05_Setting_New_Log_Analytics_Workspace.png differ diff --git a/Images/05_Workspace_Summary_View.png b/Images/05_Workspace_Summary_View.png new file mode 100644 index 00000000..1d1b358a Binary files /dev/null and b/Images/05_Workspace_Summary_View.png differ diff --git a/Images/06_AIGraph_AzSDK_ModuleVersion.jpg b/Images/06_AIGraph_AzSDK_ModuleVersion.jpg deleted file mode 100644 index 33584dc7..00000000 Binary files a/Images/06_AIGraph_AzSDK_ModuleVersion.jpg and /dev/null differ diff --git a/Images/06_AIGraph_AzSDK_Usage.jpg b/Images/06_AIGraph_AzSDK_Usage.jpg deleted file mode 100644 index 4dc8e8af..00000000 Binary files a/Images/06_AIGraph_AzSDK_Usage.jpg and /dev/null differ diff --git a/Images/06_AIGraph_FailednAttestation_Drift.jpg b/Images/06_AIGraph_FailednAttestation_Drift.PNG similarity index 100% rename from Images/06_AIGraph_FailednAttestation_Drift.jpg rename to Images/06_AIGraph_FailednAttestation_Drift.PNG diff --git a/Images/06_AIGraph_ModuleVersion.PNG b/Images/06_AIGraph_ModuleVersion.PNG new file mode 100644 index 00000000..d0e1458c Binary files /dev/null and b/Images/06_AIGraph_ModuleVersion.PNG differ diff --git a/Images/06_AIGraph_AzSDK_RunbookVersion.jpg b/Images/06_AIGraph_RunbookVersion.PNG similarity index 100% rename from Images/06_AIGraph_AzSDK_RunbookVersion.jpg rename to Images/06_AIGraph_RunbookVersion.PNG diff --git a/Images/06_AIGraph_AzSDK_ScanResultDistribution.jpg b/Images/06_AIGraph_ScanResultDistribution.PNG similarity index 100% rename from Images/06_AIGraph_AzSDK_ScanResultDistribution.jpg rename to Images/06_AIGraph_ScanResultDistribution.PNG diff --git a/Images/06_AIGraph_Usage.PNG b/Images/06_AIGraph_Usage.PNG new file mode 100644 index 00000000..7384d1f3 Binary files /dev/null and b/Images/06_AIGraph_Usage.PNG differ diff --git a/Images/06_Locate_Analytics_Link.PNG b/Images/06_Locate_Analytics_Link.PNG new file mode 100644 index 00000000..3d442d4b Binary files /dev/null and b/Images/06_Locate_Analytics_Link.PNG differ diff --git a/Images/06_Locate_Analytics_Link.jpg b/Images/06_Locate_Analytics_Link.jpg deleted file mode 100644 index fcd9658d..00000000 Binary files a/Images/06_Locate_Analytics_Link.jpg and /dev/null differ diff --git a/Images/06_Locate_Analytics_New_Query.jpg b/Images/06_Locate_Analytics_New_Query.PNG similarity index 100% rename from Images/06_Locate_Analytics_New_Query.jpg rename to Images/06_Locate_Analytics_New_Query.PNG diff --git a/Images/06_RenewCertfromPortal.png b/Images/06_RenewCertfromPortal.png new file mode 100644 index 00000000..ba60d6f9 Binary files /dev/null and b/Images/06_RenewCertfromPortal.png differ diff --git a/Images/06_Run_Analytics_Query.jpg b/Images/06_Run_Analytics_Query.PNG similarity index 100% rename from Images/06_Run_Analytics_Query.jpg rename to Images/06_Run_Analytics_Query.PNG diff --git a/Images/06_Setup_Create_App_Insights.jpg b/Images/06_Setup_Create_App_Insights.PNG similarity index 100% rename from Images/06_Setup_Create_App_Insights.jpg rename to Images/06_Setup_Create_App_Insights.PNG diff --git a/Images/06_Setup_Locate_AI_Instrumentation_Key.jpg b/Images/06_Setup_Locate_AI_Instrumentation_Key.PNG similarity index 100% rename from Images/06_Setup_Locate_AI_Instrumentation_Key.jpg rename to Images/06_Setup_Locate_AI_Instrumentation_Key.PNG diff --git a/Images/06_Understand_Locate_AI_Data.jpg b/Images/06_Understand_Locate_AI_Data.PNG similarity index 100% rename from Images/06_Understand_Locate_AI_Data.jpg rename to Images/06_Understand_Locate_AI_Data.PNG diff --git a/Images/07_Custom_Policy_ARMControls.png b/Images/07_Custom_Policy_ARMControls.png new file mode 100644 index 00000000..090e54af Binary files /dev/null and b/Images/07_Custom_Policy_ARMControls.png differ diff --git a/Images/07_Custom_Policy_AttestationExpiryReport.png b/Images/07_Custom_Policy_AttestationExpiryReport.png new file mode 100644 index 00000000..6a2a4625 Binary files /dev/null and b/Images/07_Custom_Policy_AttestationExpiryReport.png differ diff --git a/Images/07_Custom_Policy_AttestationExpiryReportOutput.png b/Images/07_Custom_Policy_AttestationExpiryReportOutput.png new file mode 100644 index 00000000..c5aac5b9 Binary files /dev/null and b/Images/07_Custom_Policy_AttestationExpiryReportOutput.png differ diff --git a/Images/07_Custom_Policy_IWROutput.png b/Images/07_Custom_Policy_IWROutput.png new file mode 100644 index 00000000..7daf856d Binary files /dev/null and b/Images/07_Custom_Policy_IWROutput.png differ diff --git a/Images/07_Custom_Policy_Output_Folder_path.PNG b/Images/07_Custom_Policy_Output_Folder_path.PNG new file mode 100644 index 00000000..a22f6e1a Binary files /dev/null and b/Images/07_Custom_Policy_Output_Folder_path.PNG differ diff --git a/Images/07_Custom_Policy_Scan_Result.PNG b/Images/07_Custom_Policy_Scan_Result.PNG new file mode 100644 index 00000000..a0e9aa68 Binary files /dev/null and b/Images/07_Custom_Policy_Scan_Result.PNG differ diff --git a/Images/07_OrgPolicy_AttestationExpiryOverride.png b/Images/07_OrgPolicy_AttestationExpiryOverride.png new file mode 100644 index 00000000..b6bdd5a0 Binary files /dev/null and b/Images/07_OrgPolicy_AttestationExpiryOverride.png differ diff --git a/Images/07_OrgPolicy_AttestationFlow.png b/Images/07_OrgPolicy_AttestationFlow.png new file mode 100644 index 00000000..c69bb4c8 Binary files /dev/null and b/Images/07_OrgPolicy_AttestationFlow.png differ diff --git a/Images/07_OrgPolicy_AzSDK_Local_Policy_Folder.PNG b/Images/07_OrgPolicy_AzSDK_Local_Policy_Folder.PNG deleted file mode 100644 index c9bd77e0..00000000 Binary files a/Images/07_OrgPolicy_AzSDK_Local_Policy_Folder.PNG and /dev/null differ diff --git a/Images/07_OrgPolicy_Big_Picture.PNG b/Images/07_OrgPolicy_Big_Picture.PNG new file mode 100644 index 00000000..90d87ee7 Binary files /dev/null and b/Images/07_OrgPolicy_Big_Picture.PNG differ diff --git a/Images/07_OrgPolicy_CAVersionSummary.PNG b/Images/07_OrgPolicy_CAVersionSummary.PNG new file mode 100644 index 00000000..8baa2f0f Binary files /dev/null and b/Images/07_OrgPolicy_CAVersionSummary.PNG differ diff --git a/Images/07_OrgPolicy_CA_PolicyCheck-0.PNG b/Images/07_OrgPolicy_CA_PolicyCheck-0.PNG new file mode 100644 index 00000000..a1511ca0 Binary files /dev/null and b/Images/07_OrgPolicy_CA_PolicyCheck-0.PNG differ diff --git a/Images/07_OrgPolicy_CA_PolicyCheck-1.PNG b/Images/07_OrgPolicy_CA_PolicyCheck-1.PNG new file mode 100644 index 00000000..62c3d66c Binary files /dev/null and b/Images/07_OrgPolicy_CA_PolicyCheck-1.PNG differ diff --git a/Images/07_OrgPolicy_CA_PolicyCheck-2.PNG b/Images/07_OrgPolicy_CA_PolicyCheck-2.PNG new file mode 100644 index 00000000..da2d7460 Binary files /dev/null and b/Images/07_OrgPolicy_CA_PolicyCheck-2.PNG differ diff --git a/Images/07_OrgPolicy_CA_PolicyCheck-3.PNG b/Images/07_OrgPolicy_CA_PolicyCheck-3.PNG new file mode 100644 index 00000000..f00a8858 Binary files /dev/null and b/Images/07_OrgPolicy_CA_PolicyCheck-3.PNG differ diff --git a/Images/07_OrgPolicy_Chg_Org_Policy_Msg.PNG b/Images/07_OrgPolicy_Chg_Org_Policy_Msg.PNG new file mode 100644 index 00000000..e46035c1 Binary files /dev/null and b/Images/07_OrgPolicy_Chg_Org_Policy_Msg.PNG differ diff --git a/Images/07_OrgPolicy_Chg_Org_Policy_Msg_PS.PNG b/Images/07_OrgPolicy_Chg_Org_Policy_Msg_PS.PNG new file mode 100644 index 00000000..24bac5ac Binary files /dev/null and b/Images/07_OrgPolicy_Chg_Org_Policy_Msg_PS.PNG differ diff --git a/Images/07_OrgPolicy_Chg_SCMD_Edit.PNG b/Images/07_OrgPolicy_Chg_SCMD_Edit.PNG new file mode 100644 index 00000000..49994456 Binary files /dev/null and b/Images/07_OrgPolicy_Chg_SCMD_Edit.PNG differ diff --git a/Images/07_OrgPolicy_Chg_SCMD_Entry.PNG b/Images/07_OrgPolicy_Chg_SCMD_Entry.PNG new file mode 100644 index 00000000..44a695b9 Binary files /dev/null and b/Images/07_OrgPolicy_Chg_SCMD_Entry.PNG differ diff --git a/Images/07_OrgPolicy_Chg_SVT_JSON.PNG b/Images/07_OrgPolicy_Chg_SVT_JSON.PNG index 5c218d4c..60faa42d 100644 Binary files a/Images/07_OrgPolicy_Chg_SVT_JSON.PNG and b/Images/07_OrgPolicy_Chg_SVT_JSON.PNG differ diff --git a/Images/07_OrgPolicy_CopyConfiguration.png b/Images/07_OrgPolicy_CopyConfiguration.png new file mode 100644 index 00000000..d9db4d10 Binary files /dev/null and b/Images/07_OrgPolicy_CopyConfiguration.png differ diff --git a/Images/07_OrgPolicy_Installation.PNG b/Images/07_OrgPolicy_Installation.PNG new file mode 100644 index 00000000..928d1612 Binary files /dev/null and b/Images/07_OrgPolicy_Installation.PNG differ diff --git a/Images/07_OrgPolicy_LocalSettings.PNG b/Images/07_OrgPolicy_LocalSettings.PNG new file mode 100644 index 00000000..7178bc07 Binary files /dev/null and b/Images/07_OrgPolicy_LocalSettings.PNG differ diff --git a/Images/07_OrgPolicy_Local_Policy_Folder.PNG b/Images/07_OrgPolicy_Local_Policy_Folder.PNG new file mode 100644 index 00000000..4d93a371 Binary files /dev/null and b/Images/07_OrgPolicy_Local_Policy_Folder.PNG differ diff --git a/Images/07_OrgPolicy_MonitoringDashboard.png b/Images/07_OrgPolicy_MonitoringDashboard.png new file mode 100644 index 00000000..9a808bb3 Binary files /dev/null and b/Images/07_OrgPolicy_MonitoringDashboard.png differ diff --git a/Images/07_OrgPolicy_Old_Version_Warning.PNG b/Images/07_OrgPolicy_Old_Version_Warning.PNG new file mode 100644 index 00000000..0a3f164b Binary files /dev/null and b/Images/07_OrgPolicy_Old_Version_Warning.PNG differ diff --git a/Images/07_OrgPolicy_Online_Policy_Flow.PNG b/Images/07_OrgPolicy_Online_Policy_Flow.PNG new file mode 100644 index 00000000..4354bd97 Binary files /dev/null and b/Images/07_OrgPolicy_Online_Policy_Flow.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata.PNG new file mode 100644 index 00000000..9d1002a0 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_01.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_01.PNG new file mode 100644 index 00000000..43022953 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_01.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_02.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_02.PNG new file mode 100644 index 00000000..c8e24089 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_02.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_03.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_03.PNG new file mode 100644 index 00000000..7b9cba76 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_03.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_04.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_04.PNG new file mode 100644 index 00000000..1337d5ee Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_04.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_05.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_05.PNG new file mode 100644 index 00000000..3ac15383 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_05.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_06.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_06.PNG new file mode 100644 index 00000000..2278fbcc Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_06.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_07.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_07.PNG new file mode 100644 index 00000000..8a773aae Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_07.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_08.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_08.PNG new file mode 100644 index 00000000..18734c5d Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_08.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_09.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_09.PNG new file mode 100644 index 00000000..0251e3a8 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_09.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_10.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_10.PNG new file mode 100644 index 00000000..00d2135a Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_10.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_11.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_11.PNG new file mode 100644 index 00000000..9b395771 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_11.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_12.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_12.PNG new file mode 100644 index 00000000..67355bcf Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_12.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_13.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_13.PNG new file mode 100644 index 00000000..ef381ca0 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_13.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_14.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_14.PNG new file mode 100644 index 00000000..094aa71b Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_14.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_15.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_15.PNG new file mode 100644 index 00000000..d034adef Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_15.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_16.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_16.PNG new file mode 100644 index 00000000..fef95471 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_16.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_17.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_17.PNG new file mode 100644 index 00000000..aefab6ae Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_17.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_18.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_18.PNG new file mode 100644 index 00000000..f7f17dcc Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_18.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_19.PNG b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_19.PNG new file mode 100644 index 00000000..abbddef7 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_19.PNG differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_21.png b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_21.png new file mode 100644 index 00000000..6077ae35 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_21.png differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_22.png b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_22.png new file mode 100644 index 00000000..622bdf3e Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_22.png differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_24.png b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_24.png new file mode 100644 index 00000000..84dd211a Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_24.png differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_25.png b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_25.png new file mode 100644 index 00000000..34891578 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_25.png differ diff --git a/Images/07_OrgPolicy_PBI_OrgMetadata_AI_26.png b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_26.png new file mode 100644 index 00000000..1e62e6e4 Binary files /dev/null and b/Images/07_OrgPolicy_PBI_OrgMetadata_AI_26.png differ diff --git a/Images/07_OrgPolicy_PovisioningPolicy.PNG b/Images/07_OrgPolicy_PovisioningPolicy.PNG new file mode 100644 index 00000000..6ddbee65 Binary files /dev/null and b/Images/07_OrgPolicy_PovisioningPolicy.PNG differ diff --git a/Images/07_OrgPolicy_ServerConfigOverride.png b/Images/07_OrgPolicy_ServerConfigOverride.png new file mode 100644 index 00000000..f4e9dff7 Binary files /dev/null and b/Images/07_OrgPolicy_ServerConfigOverride.png differ diff --git a/Images/07_RenewCertfromPortal.png b/Images/07_RenewCertfromPortal.png new file mode 100644 index 00000000..2bd7d417 Binary files /dev/null and b/Images/07_RenewCertfromPortal.png differ diff --git a/Images/08_AzSK_Extension_SVT_Storage_Policy_Example.png b/Images/08_AzSK_Extension_SVT_Storage_Policy_Example.png new file mode 100644 index 00000000..f83d2177 Binary files /dev/null and b/Images/08_AzSK_Extension_SVT_Storage_Policy_Example.png differ diff --git a/Images/08_Block_Diagram_AzSK_Extension.png b/Images/08_Block_Diagram_AzSK_Extension.png new file mode 100644 index 00000000..32539eb9 Binary files /dev/null and b/Images/08_Block_Diagram_AzSK_Extension.png differ diff --git a/Images/08_Info_BasicInfo_PS.PNG b/Images/08_Info_BasicInfo_PS.PNG deleted file mode 100644 index 3a80b71f..00000000 Binary files a/Images/08_Info_BasicInfo_PS.PNG and /dev/null differ diff --git a/Images/08_Info_ComplianceInfo_Summary_DetailedCSV.PNG b/Images/08_Info_ComplianceInfo_Summary_DetailedCSV.PNG new file mode 100644 index 00000000..744e7a6c Binary files /dev/null and b/Images/08_Info_ComplianceInfo_Summary_DetailedCSV.PNG differ diff --git a/Images/08_Info_ComplianceInfo_Summary_PS.PNG b/Images/08_Info_ComplianceInfo_Summary_PS.PNG new file mode 100644 index 00000000..e19be084 Binary files /dev/null and b/Images/08_Info_ComplianceInfo_Summary_PS.PNG differ diff --git a/Images/08_Info_ControlInfo_PS.PNG b/Images/08_Info_ControlInfo_PS.PNG deleted file mode 100644 index 341913aa..00000000 Binary files a/Images/08_Info_ControlInfo_PS.PNG and /dev/null differ diff --git a/Images/08_Info_ControlInfo_Summary_PS.PNG b/Images/08_Info_ControlInfo_Summary_PS.PNG new file mode 100644 index 00000000..b84be2af Binary files /dev/null and b/Images/08_Info_ControlInfo_Summary_PS.PNG differ diff --git a/Images/08_Info_ControlInfo_Verbose_PS.PNG b/Images/08_Info_ControlInfo_Verbose_PS.PNG new file mode 100644 index 00000000..3ddf040c Binary files /dev/null and b/Images/08_Info_ControlInfo_Verbose_PS.PNG differ diff --git a/Images/08_Info_HostInfo_PS.PNG b/Images/08_Info_HostInfo_PS.PNG new file mode 100644 index 00000000..f3ea6981 Binary files /dev/null and b/Images/08_Info_HostInfo_PS.PNG differ diff --git a/Images/08_Info_SubscriptionInfo_PS.PNG b/Images/08_Info_SubscriptionInfo_PS.PNG new file mode 100644 index 00000000..6469bd34 Binary files /dev/null and b/Images/08_Info_SubscriptionInfo_PS.PNG differ diff --git a/Images/08_Info_UserComments_PS.JPG b/Images/08_Info_UserComments_PS.JPG new file mode 100644 index 00000000..bbd6cecb Binary files /dev/null and b/Images/08_Info_UserComments_PS.JPG differ diff --git a/Images/08_RenewCertfromPortalError.PNG b/Images/08_RenewCertfromPortalError.PNG new file mode 100644 index 00000000..c4252656 Binary files /dev/null and b/Images/08_RenewCertfromPortalError.PNG differ diff --git a/Images/09_ADO_AddADOScannerTask.png b/Images/09_ADO_AddADOScannerTask.png new file mode 100644 index 00000000..58a2c324 Binary files /dev/null and b/Images/09_ADO_AddADOScannerTask.png differ diff --git a/Images/09_ADO_AddDashboard.png b/Images/09_ADO_AddDashboard.png new file mode 100644 index 00000000..18928053 Binary files /dev/null and b/Images/09_ADO_AddDashboard.png differ diff --git a/Images/09_ADO_AddOrgSummaryWidget.png b/Images/09_ADO_AddOrgSummaryWidget.png new file mode 100644 index 00000000..20452452 Binary files /dev/null and b/Images/09_ADO_AddOrgSummaryWidget.png differ diff --git a/Images/09_ADO_AddServiceConnection.png b/Images/09_ADO_AddServiceConnection.png new file mode 100644 index 00000000..a73f0c7c Binary files /dev/null and b/Images/09_ADO_AddServiceConnection.png differ diff --git a/Images/09_ADO_AddTaskDetails.png b/Images/09_ADO_AddTaskDetails.png new file mode 100644 index 00000000..fc672bb5 Binary files /dev/null and b/Images/09_ADO_AddTaskDetails.png differ diff --git a/Images/09_ADO_ExtensionDetails.png b/Images/09_ADO_ExtensionDetails.png new file mode 100644 index 00000000..0bc7b920 Binary files /dev/null and b/Images/09_ADO_ExtensionDetails.png differ diff --git a/Images/09_ADO_OrgLevelDashboard.png b/Images/09_ADO_OrgLevelDashboard.png new file mode 100644 index 00000000..d441743e Binary files /dev/null and b/Images/09_ADO_OrgLevelDashboard.png differ diff --git a/Images/09_ADO_Org_Policy1.png b/Images/09_ADO_Org_Policy1.png new file mode 100644 index 00000000..1cb2a823 Binary files /dev/null and b/Images/09_ADO_Org_Policy1.png differ diff --git a/Images/09_ADO_Org_Policy2.png b/Images/09_ADO_Org_Policy2.png new file mode 100644 index 00000000..f0a89d78 Binary files /dev/null and b/Images/09_ADO_Org_Policy2.png differ diff --git a/Images/09_ADO_Org_Policy3.png b/Images/09_ADO_Org_Policy3.png new file mode 100644 index 00000000..80903f21 Binary files /dev/null and b/Images/09_ADO_Org_Policy3.png differ diff --git a/Images/09_ADO_Org_Policy4.png b/Images/09_ADO_Org_Policy4.png new file mode 100644 index 00000000..fabf50e0 Binary files /dev/null and b/Images/09_ADO_Org_Policy4.png differ diff --git a/Images/09_ADO_Org_Policy5.png b/Images/09_ADO_Org_Policy5.png new file mode 100644 index 00000000..294f2862 Binary files /dev/null and b/Images/09_ADO_Org_Policy5.png differ diff --git a/Images/09_ADO_Org_Policy6.png b/Images/09_ADO_Org_Policy6.png new file mode 100644 index 00000000..cc9233eb Binary files /dev/null and b/Images/09_ADO_Org_Policy6.png differ diff --git a/Images/09_ADO_ProjectComponentLevl.png b/Images/09_ADO_ProjectComponentLevl.png new file mode 100644 index 00000000..8172b7bf Binary files /dev/null and b/Images/09_ADO_ProjectComponentLevl.png differ diff --git a/Images/09_ADO_ScanImage-1.png b/Images/09_ADO_ScanImage-1.png new file mode 100644 index 00000000..39f54dfa Binary files /dev/null and b/Images/09_ADO_ScanImage-1.png differ diff --git a/Images/09_ADO_ScanImage-2.png b/Images/09_ADO_ScanImage-2.png new file mode 100644 index 00000000..738387de Binary files /dev/null and b/Images/09_ADO_ScanImage-2.png differ diff --git a/Images/09_ADO_ScheduleTrigger.png b/Images/09_ADO_ScheduleTrigger.png new file mode 100644 index 00000000..285dff3a Binary files /dev/null and b/Images/09_ADO_ScheduleTrigger.png differ diff --git a/Images/09_ADO_TriggerPipeline.png b/Images/09_ADO_TriggerPipeline.png new file mode 100644 index 00000000..4b30c91f Binary files /dev/null and b/Images/09_ADO_TriggerPipeline.png differ diff --git a/Images/09_CA_FunctionApp.PNG b/Images/09_CA_FunctionApp.PNG new file mode 100644 index 00000000..2160415f Binary files /dev/null and b/Images/09_CA_FunctionApp.PNG differ diff --git a/Images/09_CA_Laws_Query.PNG b/Images/09_CA_Laws_Query.PNG new file mode 100644 index 00000000..b54e0629 Binary files /dev/null and b/Images/09_CA_Laws_Query.PNG differ diff --git a/Images/09_CA_Storage_Logs.PNG b/Images/09_CA_Storage_Logs.PNG new file mode 100644 index 00000000..b01d19ab Binary files /dev/null and b/Images/09_CA_Storage_Logs.PNG differ diff --git a/Images/09_SVT_Attest_1.png b/Images/09_SVT_Attest_1.png new file mode 100644 index 00000000..d22cec8a Binary files /dev/null and b/Images/09_SVT_Attest_1.png differ diff --git a/Images/09_SVT_Attest_2.png b/Images/09_SVT_Attest_2.png new file mode 100644 index 00000000..af30d1ab Binary files /dev/null and b/Images/09_SVT_Attest_2.png differ diff --git a/Images/09_SVT_Attest_3.png b/Images/09_SVT_Attest_3.png new file mode 100644 index 00000000..228f8524 Binary files /dev/null and b/Images/09_SVT_Attest_3.png differ diff --git a/Images/10_ADO_ScheduleTrigger.png b/Images/10_ADO_ScheduleTrigger.png new file mode 100644 index 00000000..14125f10 Binary files /dev/null and b/Images/10_ADO_ScheduleTrigger.png differ diff --git a/Images/10_ADO_TriggerPipeline.png b/Images/10_ADO_TriggerPipeline.png new file mode 100644 index 00000000..4293b6d9 Binary files /dev/null and b/Images/10_ADO_TriggerPipeline.png differ diff --git a/Images/12_AppObjectId.png b/Images/12_AppObjectId.png new file mode 100644 index 00000000..1a4cd64e Binary files /dev/null and b/Images/12_AppObjectId.png differ diff --git a/Images/12_AppRegistration.png b/Images/12_AppRegistration.png new file mode 100644 index 00000000..a0fe1649 Binary files /dev/null and b/Images/12_AppRegistration.png differ diff --git a/Images/12_TSS_CommandOutput.png b/Images/12_TSS_CommandOutput.png new file mode 100644 index 00000000..6e5badd9 Binary files /dev/null and b/Images/12_TSS_CommandOutput.png differ diff --git a/Images/12_TSS_PBIDashboardComplianceDetails.png b/Images/12_TSS_PBIDashboardComplianceDetails.png new file mode 100644 index 00000000..682cb6eb Binary files /dev/null and b/Images/12_TSS_PBIDashboardComplianceDetails.png differ diff --git a/Images/12_TSS_PBIDashboardComplianceSummary.png b/Images/12_TSS_PBIDashboardComplianceSummary.png new file mode 100644 index 00000000..e48ff666 Binary files /dev/null and b/Images/12_TSS_PBIDashboardComplianceSummary.png differ diff --git a/Images/12_TSS_PBIDashboardInventoryOverview.png b/Images/12_TSS_PBIDashboardInventoryOverview.png new file mode 100644 index 00000000..670e6b59 Binary files /dev/null and b/Images/12_TSS_PBIDashboardInventoryOverview.png differ diff --git a/Images/12_TSS_Processor_WebJobs.png b/Images/12_TSS_Processor_WebJobs.png new file mode 100644 index 00000000..8236d755 Binary files /dev/null and b/Images/12_TSS_Processor_WebJobs.png differ diff --git a/Images/12_TSS_Resource_Group.png b/Images/12_TSS_Resource_Group.png new file mode 100644 index 00000000..9c22e048 Binary files /dev/null and b/Images/12_TSS_Resource_Group.png differ diff --git a/Images/12_TSS_Scheduler_Webjobs.png b/Images/12_TSS_Scheduler_Webjobs.png new file mode 100644 index 00000000..a061c2fd Binary files /dev/null and b/Images/12_TSS_Scheduler_Webjobs.png differ diff --git a/Images/12_TSS_Storage_Queue.png b/Images/12_TSS_Storage_Queue.png new file mode 100644 index 00000000..8104339c Binary files /dev/null and b/Images/12_TSS_Storage_Queue.png differ diff --git a/Images/12_TenantSetupInternals.png b/Images/12_TenantSetupInternals.png new file mode 100644 index 00000000..7c764f65 Binary files /dev/null and b/Images/12_TenantSetupInternals.png differ diff --git a/Images/13_TSS_LAWS_AgentManagement.png b/Images/13_TSS_LAWS_AgentManagement.png new file mode 100644 index 00000000..f861b45e Binary files /dev/null and b/Images/13_TSS_LAWS_AgentManagement.png differ diff --git a/Images/13_TSS_LAWS_Query_Logs.png b/Images/13_TSS_LAWS_Query_Logs.png new file mode 100644 index 00000000..244b7640 Binary files /dev/null and b/Images/13_TSS_LAWS_Query_Logs.png differ diff --git a/Images/13_TSS_LAWS_View_Logs.png b/Images/13_TSS_LAWS_View_Logs.png new file mode 100644 index 00000000..7d7671d8 Binary files /dev/null and b/Images/13_TSS_LAWS_View_Logs.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_1.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_1.png new file mode 100644 index 00000000..86418138 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_1.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_2.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_2.png new file mode 100644 index 00000000..150627c4 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_2.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_3.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_3.png new file mode 100644 index 00000000..6e34f936 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_3.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_4.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_4.png new file mode 100644 index 00000000..0321223f Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_4.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_5.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_5.png new file mode 100644 index 00000000..a84ce280 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_5.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_6.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_6.png new file mode 100644 index 00000000..9842465d Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_6.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_7.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_7.png new file mode 100644 index 00000000..f9334996 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_7.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_8.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_8.png new file mode 100644 index 00000000..588e28fe Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_8.png differ diff --git a/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_9.png b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_9.png new file mode 100644 index 00000000..33fc5754 Binary files /dev/null and b/Images/13_TSS_OrgPolicy_PBI_OrgMetadata_LA_9.png differ diff --git a/Images/13_TSS_PBIDashboardComplianceDetails.png b/Images/13_TSS_PBIDashboardComplianceDetails.png new file mode 100644 index 00000000..7ca2af60 Binary files /dev/null and b/Images/13_TSS_PBIDashboardComplianceDetails.png differ diff --git a/Images/13_TSS_PBIDashboardComplianceSummary.png b/Images/13_TSS_PBIDashboardComplianceSummary.png new file mode 100644 index 00000000..df2fe292 Binary files /dev/null and b/Images/13_TSS_PBIDashboardComplianceSummary.png differ diff --git a/Images/13_TSS_PBIDashboardInventoryOverview.png b/Images/13_TSS_PBIDashboardInventoryOverview.png new file mode 100644 index 00000000..0986b56f Binary files /dev/null and b/Images/13_TSS_PBIDashboardInventoryOverview.png differ diff --git a/Images/ADB-Step1.png b/Images/ADB-Step1.png new file mode 100644 index 00000000..1c537872 Binary files /dev/null and b/Images/ADB-Step1.png differ diff --git a/Images/ADB-Step2.png b/Images/ADB-Step2.png new file mode 100644 index 00000000..64470251 Binary files /dev/null and b/Images/ADB-Step2.png differ diff --git a/Images/ADB-Step3.png b/Images/ADB-Step3.png new file mode 100644 index 00000000..069f38c0 Binary files /dev/null and b/Images/ADB-Step3.png differ diff --git a/Images/ADB-Step4.png b/Images/ADB-Step4.png new file mode 100644 index 00000000..981b094f Binary files /dev/null and b/Images/ADB-Step4.png differ diff --git a/Images/ADO/09_ADO_Install-AzSKMonitoringSolution.png b/Images/ADO/09_ADO_Install-AzSKMonitoringSolution.png new file mode 100644 index 00000000..67ab0069 Binary files /dev/null and b/Images/ADO/09_ADO_Install-AzSKMonitoringSolution.png differ diff --git a/Images/ADO/09_Install_Autoupdate.PNG b/Images/ADO/09_Install_Autoupdate.PNG new file mode 100644 index 00000000..581a625e Binary files /dev/null and b/Images/ADO/09_Install_Autoupdate.PNG differ diff --git a/Images/ADO/09_Install_Autoupdate_Workflow.PNG b/Images/ADO/09_Install_Autoupdate_Workflow.PNG new file mode 100644 index 00000000..d976b4d7 Binary files /dev/null and b/Images/ADO/09_Install_Autoupdate_Workflow.PNG differ diff --git a/Images/ADO/09_Log_Analytics_Workbook_Overview.png b/Images/ADO/09_Log_Analytics_Workbook_Overview.png new file mode 100644 index 00000000..7c76fcc7 Binary files /dev/null and b/Images/ADO/09_Log_Analytics_Workbook_Overview.png differ diff --git a/Images/ADO/09_Log_Analytics_Workbook_View.png b/Images/ADO/09_Log_Analytics_Workbook_View.png new file mode 100644 index 00000000..e4ea4712 Binary files /dev/null and b/Images/ADO/09_Log_Analytics_Workbook_View.png differ diff --git a/Images/ADO/09_Log_Analytics_Workspace_Logs_Query.png b/Images/ADO/09_Log_Analytics_Workspace_Logs_Query.png new file mode 100644 index 00000000..0316286c Binary files /dev/null and b/Images/ADO/09_Log_Analytics_Workspace_Logs_Query.png differ diff --git a/Images/ADO/09_Log_Analytics_Workspace_New_View.png b/Images/ADO/09_Log_Analytics_Workspace_New_View.png new file mode 100644 index 00000000..c0a572fb Binary files /dev/null and b/Images/ADO/09_Log_Analytics_Workspace_New_View.png differ diff --git a/Images/ADO/09_Log_Analytics_Workspace_Query_Duration.png b/Images/ADO/09_Log_Analytics_Workspace_Query_Duration.png new file mode 100644 index 00000000..25889e4a Binary files /dev/null and b/Images/ADO/09_Log_Analytics_Workspace_Query_Duration.png differ diff --git a/Images/ADO/09_Workspace_Summary_View.png b/Images/ADO/09_Workspace_Summary_View.png new file mode 100644 index 00000000..26f27fd8 Binary files /dev/null and b/Images/ADO/09_Workspace_Summary_View.png differ diff --git a/Images/ADO_BugLogging_BugJSON.png b/Images/ADO_BugLogging_BugJSON.png new file mode 100644 index 00000000..0cabf812 Binary files /dev/null and b/Images/ADO_BugLogging_BugJSON.png differ diff --git a/Images/ADO_BugLogging_BugSummary.png b/Images/ADO_BugLogging_BugSummary.png new file mode 100644 index 00000000..988d0b2c Binary files /dev/null and b/Images/ADO_BugLogging_BugSummary.png differ diff --git a/Images/ADO_BugLogging_BugTemplate.png b/Images/ADO_BugLogging_BugTemplate.png new file mode 100644 index 00000000..7e39b8e7 Binary files /dev/null and b/Images/ADO_BugLogging_BugTemplate.png differ diff --git a/Images/ADO_BugLogging_OrgPolicy.png b/Images/ADO_BugLogging_OrgPolicy.png new file mode 100644 index 00000000..fabf50e0 Binary files /dev/null and b/Images/ADO_BugLogging_OrgPolicy.png differ diff --git a/Images/AKS-Step1.png b/Images/AKS-Step1.png new file mode 100644 index 00000000..7c2b1610 Binary files /dev/null and b/Images/AKS-Step1.png differ diff --git a/Images/AKS-Step2.png b/Images/AKS-Step2.png new file mode 100644 index 00000000..d548e1e4 Binary files /dev/null and b/Images/AKS-Step2.png differ diff --git a/Images/AKS-Step3.png b/Images/AKS-Step3.png new file mode 100644 index 00000000..20dc47ae Binary files /dev/null and b/Images/AKS-Step3.png differ diff --git a/Images/AKS-Step4a.png b/Images/AKS-Step4a.png new file mode 100644 index 00000000..f5f49ced Binary files /dev/null and b/Images/AKS-Step4a.png differ diff --git a/Images/AKS-Step4b.PNG b/Images/AKS-Step4b.PNG new file mode 100644 index 00000000..c5f375bc Binary files /dev/null and b/Images/AKS-Step4b.PNG differ diff --git a/Images/ARMChecker_Orgpolicy_Variables.jpg b/Images/ARMChecker_Orgpolicy_Variables.jpg new file mode 100644 index 00000000..19859467 Binary files /dev/null and b/Images/ARMChecker_Orgpolicy_Variables.jpg differ diff --git a/Images/Alerting_and_Monitoring.PNG b/Images/Alerting_and_Monitoring.PNG deleted file mode 100644 index 9e8f1f1c..00000000 Binary files a/Images/Alerting_and_Monitoring.PNG and /dev/null differ diff --git a/Images/Alerting_and_Monitoring.png b/Images/Alerting_and_Monitoring.png new file mode 100644 index 00000000..722069d1 Binary files /dev/null and b/Images/Alerting_and_Monitoring.png differ diff --git a/Images/AzSDK_Logo.PNG b/Images/AzSK_Logo.PNG similarity index 100% rename from Images/AzSDK_Logo.PNG rename to Images/AzSK_Logo.PNG diff --git a/Images/CarouselImages/CarouselImage01.png b/Images/CarouselImages/CarouselImage01.png index cf1c2ef4..7dddf497 100644 Binary files a/Images/CarouselImages/CarouselImage01.png and b/Images/CarouselImages/CarouselImage01.png differ diff --git a/Images/CarouselImages/CarouselImage02.png b/Images/CarouselImages/CarouselImage02.png index d1702c58..5a867e89 100644 Binary files a/Images/CarouselImages/CarouselImage02.png and b/Images/CarouselImages/CarouselImage02.png differ diff --git a/Images/CarouselImages/CarouselImage04.png b/Images/CarouselImages/CarouselImage04.png index 9809a1fd..7d13d931 100644 Binary files a/Images/CarouselImages/CarouselImage04.png and b/Images/CarouselImages/CarouselImage04.png differ diff --git a/Images/CarouselImages/CarouselImage06.png b/Images/CarouselImages/CarouselImage06.png index 5f0b4812..4766158d 100644 Binary files a/Images/CarouselImages/CarouselImage06.png and b/Images/CarouselImages/CarouselImage06.png differ diff --git a/Images/Continous_Assurance.PNG b/Images/Continous_Assurance.PNG deleted file mode 100644 index d3b6120d..00000000 Binary files a/Images/Continous_Assurance.PNG and /dev/null differ diff --git a/Images/Continous_Assurance.png b/Images/Continous_Assurance.png new file mode 100644 index 00000000..90d04d45 Binary files /dev/null and b/Images/Continous_Assurance.png differ diff --git a/Images/GADI_ControlInfo.png b/Images/GADI_ControlInfo.png new file mode 100644 index 00000000..2b0195fe Binary files /dev/null and b/Images/GADI_ControlInfo.png differ diff --git a/Images/GADI_HostInfo.png b/Images/GADI_HostInfo.png new file mode 100644 index 00000000..9c3aae0e Binary files /dev/null and b/Images/GADI_HostInfo.png differ diff --git a/Images/HDI-Step1.png b/Images/HDI-Step1.png new file mode 100644 index 00000000..3f5cab7f Binary files /dev/null and b/Images/HDI-Step1.png differ diff --git a/Images/HDI-Step2.png b/Images/HDI-Step2.png new file mode 100644 index 00000000..f3dc8524 Binary files /dev/null and b/Images/HDI-Step2.png differ diff --git a/Images/HDI-Step3.png b/Images/HDI-Step3.png new file mode 100644 index 00000000..8241488c Binary files /dev/null and b/Images/HDI-Step3.png differ diff --git a/Images/HDI-Step5.png b/Images/HDI-Step5.png new file mode 100644 index 00000000..223c67b1 Binary files /dev/null and b/Images/HDI-Step5.png differ diff --git a/Images/HDI-Step6.png b/Images/HDI-Step6.png new file mode 100644 index 00000000..82930cd5 Binary files /dev/null and b/Images/HDI-Step6.png differ diff --git a/Images/Icons/AzSDK_Favicon.png b/Images/Icons/AzSK_Favicon.png similarity index 100% rename from Images/Icons/AzSDK_Favicon.png rename to Images/Icons/AzSK_Favicon.png diff --git a/Images/Icons/AzSDK_Logo.png b/Images/Icons/AzSK_Logo.png similarity index 100% rename from Images/Icons/AzSDK_Logo.png rename to Images/Icons/AzSK_Logo.png diff --git a/Images/OMS_Blade_RS2.PNG b/Images/OMS_Blade_RS2.PNG deleted file mode 100644 index 4d8bdd18..00000000 Binary files a/Images/OMS_Blade_RS2.PNG and /dev/null differ diff --git a/Images/OMS_Blade_RS3.PNG b/Images/OMS_Blade_RS3.PNG deleted file mode 100644 index 761d2975..00000000 Binary files a/Images/OMS_Blade_RS3.PNG and /dev/null differ diff --git a/Images/OMS_Blade_RS4.PNG b/Images/OMS_Blade_RS4.PNG deleted file mode 100644 index 34a3a11d..00000000 Binary files a/Images/OMS_Blade_RS4.PNG and /dev/null differ diff --git a/Images/Secure_DevOps_Kit_Azure.PNG b/Images/Secure_DevOps_Kit_Azure.PNG index cf1c2ef4..377d606e 100644 Binary files a/Images/Secure_DevOps_Kit_Azure.PNG and b/Images/Secure_DevOps_Kit_Azure.PNG differ diff --git a/Images/Secure_Development.png b/Images/Secure_Development.png index 09a5f1fc..2cdb9dc6 100644 Binary files a/Images/Secure_Development.png and b/Images/Secure_Development.png differ diff --git a/Images/Security_In_CICD.jpg b/Images/Security_In_CICD.jpg deleted file mode 100644 index 47c707c7..00000000 Binary files a/Images/Security_In_CICD.jpg and /dev/null differ diff --git a/Images/Security_In_CICD.png b/Images/Security_In_CICD.png new file mode 100644 index 00000000..29063fbb Binary files /dev/null and b/Images/Security_In_CICD.png differ diff --git a/Images/Security_In_CICD_VMMarketplace.jpg b/Images/Security_In_CICD_VMMarketplace.jpg index 0ca88a7c..80d72975 100644 Binary files a/Images/Security_In_CICD_VMMarketplace.jpg and b/Images/Security_In_CICD_VMMarketplace.jpg differ diff --git a/Images/Security_Telemetry.PNG b/Images/Security_Telemetry.PNG deleted file mode 100644 index 0c9fb4de..00000000 Binary files a/Images/Security_Telemetry.PNG and /dev/null differ diff --git a/Images/Security_Telemetry.png b/Images/Security_Telemetry.png new file mode 100644 index 00000000..3a921bf8 Binary files /dev/null and b/Images/Security_Telemetry.png differ diff --git a/Images/Subscription_Security.JPG b/Images/Subscription_Security.JPG deleted file mode 100644 index 40572d83..00000000 Binary files a/Images/Subscription_Security.JPG and /dev/null differ diff --git a/Images/Subscription_Security.png b/Images/Subscription_Security.png new file mode 100644 index 00000000..dc431000 Binary files /dev/null and b/Images/Subscription_Security.png differ diff --git a/README.md b/README.md index 5cbb53e3..3212fd4a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- +> The Secure DevOps Kit for Azure (AzSK) was created by the Core Services Engineering & Operations (CSEO) division at Microsoft, to help accelerate Microsoft IT's adoption of Azure. We have shared AzSK and its documentation with the community to provide guidance for rapidly scanning, deploying and operationalizing cloud resources, across the different stages of DevOps, while maintaining controls on security and governance. +
    AzSK is not an official Microsoft product – rather an attempt to share Microsoft CSEO's best practices with the community.. # Secure DevOps Kit for Azure (AzSK) ## Content @@ -46,7 +50,7 @@ These use cases will tell you which commands you will need to run, what would ha By leveraging the extensive degree of automation that AzSK has to offer, ability to centrally deploy and manage policies/rules and the uniform behavior of scripts across the kit, you can save several hours of what would otherwise be manual security checks and examination. -As you get familiar with and begin to use the 'downstream' capabilities (CICD, Continuous Compliance, OMS support, etc.), the power of security automation and the seamless end-to-end experience that the AzSK unleashes will become more evident. +As you get familiar with and begin to use the 'downstream' capabilities (CICD, Continuous Compliance, Log Analytics support, etc.), the power of security automation and the seamless end-to-end experience that the AzSK unleashes will become more evident. [Back to top...](README.md#content) @@ -58,14 +62,14 @@ As you get familiar with and begin to use the 'downstream' capabilities (CICD, C [Enable secure development](02-Secure-Development/Readme.md) |
    • Security Verification Tests (SVT)
    • Security IntelliSense- VS Extension
    [Integrate security into CICD](03-Security-In-CICD/Readme.md) |
    • AzSK VS Extension-executes SVTs in a CICD pipeline
    [Continuous Assurance](04-Continous-Assurance/Readme.md) |
    • Security scanning via Azure Automation Runbooks
    -[Alerting & Monitoring](05-Alerting-and-Monitoring/Readme.md) |
    • OMS Solution for AzSK containing:
      • Security dashboard views covering security state/actions
      • Alerts with pertinent search queries
    +[Alerting & Monitoring](05-Alerting-and-Monitoring/Readme.md) |
    • Monitoring Solution for AzSK containing:
      • Security dashboard views covering security state/actions
      • Alerts with pertinent search queries
    [Cloud Risk Governance](06-Security-Telemetry/Readme.md) |
    • Control/usage telemetry through Insights
    [Back to top...](README.md#content) ### What do you want to use the secure devops kit for? As you can see from the summary description above, the "Secure DevOps Kit for Azure" (we will call it AzSK to be brief hereafter), can be used by many different stakeholders. So depending on your role in the DevOps ecosystem, one or more of the below scenarios may apply to you. The skillset needed to use the capabilities of the kit and the prerequisites you need to have on your machine will vary based on your scenario. Here are a few sample stakeholders and some points about *how* they may try to use the AzSK: -|Stakeholders / Persona |Capabilties of the kit | +|Stakeholders / Persona |Capabilities of the kit | | ---- | ---- | |**Subscription Owners**| Check the overall security health of your Azure subscription.
    Ensure that artifacts such as Alerts for important activities, ARM policy, resource locks, RBAC roles, etc. are properly provisioned. | |**Development/Engineering**| Get inline support with security tips and corrections while writing code for Azure apps (and also standard web applications in general).
    Test that Azure resources you are using for your application/solutions are configured and deployed securely.
    Enable security in CICD by including various security tests in the build/release pipelines| @@ -80,10 +84,7 @@ As you can see from the summary description above, the "Secure DevOps Kit for Az ### References - AzSK Module @PSGallery -- AzSDK Security Controls Portal @https://aka.ms/azskosstcp +- AzSK Security Controls Portal @https://aka.ms/azskosstcp - Security IntelliSense @VisualStudio Marketplace - Visual Studio Online CICD Build/Release Extension @VisualStudio Marketplace -- For any other issues or feedback please drop a mail to AzSDK Support - -[Back to top...](README.md#content) - +- For any other issues or feedback please drop a mail to AzSK Support diff --git a/ReleaseNotes/AzSKSunsetNotice.md b/ReleaseNotes/AzSKSunsetNotice.md new file mode 100644 index 00000000..0095b885 --- /dev/null +++ b/ReleaseNotes/AzSKSunsetNotice.md @@ -0,0 +1,15 @@ +# AzSK Sunset Notice + +- After close to 5 years of active development, the PowerShell/Automation-based "Secure DevOps Kit for Azure (AzSK)" is being phased out through FY21. We are transitioning to a more scalable and robust solution called Azure Tenant Security scanner (AzTS) which is based on Azure Functions and a central scan model where scans are performed via a managed identity with Reader access to subscriptions configured at management group level. This new approach helps us scale efficiently and with less process overhead to get the same level of visibility to compliance of several thousand subscriptions. It is also designed to help accelerate our migration to native security offerings in Azure such as Policy, Security Center, Management Groups, Azure Resource Graph, etc. +- At the Core Services Engineering and Operations (CSEO) division, we plan to phase out AzSK-based Continuous Assurance completely during Q3-FY21 and, furthermore, eliminate our other dependencies on AzSK (ARM Checker, DevOps Kit CICD Extensions, etc.) during Q4-FY21. We will support important bug fixes in AzSK till end of FY21. However, new security controls and features will be added only to AzTS going forward. The AzSK project repo will remain available on GitHub FY22 and beyond but without active maintenance. +- The new solution, AzTS, is available at https://aka.ms/devopskit/AzTS. This was developed by the same team that built AzSK and we have been using it to scan close to 100,000 Azure subscriptions daily for baseline control compliance across our environment over the last several months. +- As promised to all internal and external users of AzSK, we will continue to share CSEO's internal approach for cloud security and compliance and our migration path towards exclusively using native security capabilities in Azure. We believe AzTS takes us a big step closer to that. If you have a dependency on AzSK, please consider either migrating to AzTS or switching to using an approach based on native capabilities such as Azure Policy, Management Groups, Security Center, etc. + +## About our other scan modules (AAD, ADO, etc.) +The points above are about the AzSK module which is Azure-specific. For the other modules (AAD scanner, ADO scanner), we have the following guidance: + +- ADO Scanner module (AzSK.ADO) will continue to be updated and maintained by our team. It is being actively used for surfacing security risks and remediating issues in our development environments. You can directly access the ADO Scanner project at https://aka.ms/adoscanner. +- The AAD Scanner (AzSK.AAD) has been in preview mode. We have not done further development on it and there are no plans to resume work at present. + +## A note of thanks! +- Right from the time we started, we have treated AzSK as a community effort. Early adopters and users of the kit (both MS internal and external members) regularly suggested improvements - some in overview discussions, some in targeted use case/solutioning efforts and some others just over email. Almost every appealing AzSK feature we added after the initial launch has a mark of someone from outside our core team!! The toolkit matured and came a long way because of contributions from collaborators like you and we would like to thank you whole-heartedly for your inputs, ideas and contributions and, equally importantly, the confidence you expressed in us all through this journey. diff --git a/ReleaseNotes/LatestReleaseNotes.md b/ReleaseNotes/LatestReleaseNotes.md new file mode 100644 index 00000000..d364126c --- /dev/null +++ b/ReleaseNotes/LatestReleaseNotes.md @@ -0,0 +1,121 @@ +## 210115 (AzSK v.4.15.0) + +### Feature updates + +* Default TLS 1.2 setting for AzSK storage account: + + * The storage account created under AzSKRG while installing CA using Install-AzSKContinuousAssurance command,will now be set up with ‘TLS version 1.2’ and ‘Allow Blob public access’ set to ‘Disabled’ by default.In order to apply these settings to your existing AzSK storage accounts, you’ll need to run following command: + ```Powershell + Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId + ``` + +* Security Verification Tests (SVTs): + * N/A. + + +* Log Analytics: + * N/A. + + +* ARM Template Checker: + * N/A. + + +* Org policy/external user updates (for non-CSEO users): + * Storage account created as part of Org policy setup via Install-AzSKOrganizationPolicy command will now be set up with TLS version 1.2 by default.To apply this setting for your existing org policy storage accounts, you just need to run following command: + ```Powershell + Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" + + ``` + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Management of DevOps Kit-based AAD applications: + * You can list all the DevOps Kit-based service principals (used in continuous assurance) that are owned by you via the Get-AzSKInfo cmd marking those that are actively used for CA scans. + + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from earlier sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * N/A + +* SVTs: + * N/A + +* Controls: + * Fixed a bug in control ‘Azure_Subscription_AuthZ_Limit_ClassicAdmin_Count’. It will now fail in case there is an account having multiple classic admin roles e.g. account having both CoAdministrator and AccountAdministrator role + * Fixed a bug in control 'Azure_Subscription_Configure_Conditional_Access_for_PIM. The Control will flag roles that have conditional accesss policy configured but do not have required acrs tag. Expected tags are {"acrsRequired":true,"acrs":"urn:microsoft:req1"}. + * Fixed a bug in control Azure_SQLDatabase_DP_Enable_TDE. Now the control will pass if email notifications to either admins or to specific recipients are configured. + + +* Privileged Identity Management (PIM): + * N/A. + +* CICD: + * N/A. + +* ARM Template Checker: + * N/A. + +* CA: + * N/A + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A + +* Others: + * N/A + + diff --git a/ReleaseNotes/RN160930.md b/ReleaseNotes/RN160930.md new file mode 100644 index 00000000..60be342a --- /dev/null +++ b/ReleaseNotes/RN160930.md @@ -0,0 +1,18 @@ +## 160930 + +### New Features (preview): +* Subscription Security – + * Just-Enough-Administration (JEA) – Support for JEA-based administration of subscriptions. The experience of setting up JEA has been significantly improved (automated) relative to the mid-month release. As a result, trying it out will be a very smooth experience even if you are unfamiliar with JEA. We are now working on the ‘lockdown’ configuration for the JEA jump-box server. + * Subscription Health Check – Capability to scan for several subscription RBAC-hygiene related issues such as presence excessive number of admins, non-MS accounts, MFA-exempt service accounts, management certificates, etc. (See full list in the docs.) + * Provisioning of central roles and accounts – Support for provisioning and configuration of some core accounts that are required by central teams. + * Custom alert logic for subscription activity – This release enhances alerting capability with support for SMS-based alerts for critical scenarios. It includes a ‘Critical Alerts’ sample that can be used as the framework for building up smart alerting rules based on deeper analysis of the alert and event fields. E.g., sending an SMS-based alert if the caller IP is x.y.z.p ‘and’ the ‘Owner’ role was changed. Email-based notifications will continue to work as earlier for the broader set of operations. +* Dev/CICD Kit – + * Security IntelliSense – A VS plugin based on the Roslyn Framework that provides inline assistance for security code development while code is being written. The current release contains rules for about a dozen Azure secure coding practices. Apart from Azure rules, some crypto rules are also included. The plugin is capable of ‘auto-refreshing’ the rulesets it uses. + * Security Verification Tests (SVT) – New modules added for control testing coverage of Azure Data Factory, Service Fabric and Service Bus (Queue, Topics, Event Hubs). +* Alerting and Monitoring – + * Visibility of security critical events for Azure (PaaS and IaaS) resources for application teams. +Improvements/Fixes: +* Subscription Security – + * Ability to ‘uninstall’ alert package, ARM policy, etc. (equivalent of an ‘undo’). + * Notifications about disabled alerts and policies. + diff --git a/ReleaseNotes/RN161014.md b/ReleaseNotes/RN161014.md new file mode 100644 index 00000000..a5b487ea --- /dev/null +++ b/ReleaseNotes/RN161014.md @@ -0,0 +1,23 @@ +## 161014 + +### New Features (preview): +* Subscription Security + * Azure Security Center (ASC) Configuration - Added PS module that can help configure ASC for a subscription per expected policies and information (such as contact email, phone number for alerts/ incident response, etc.). +* Dev/CICD Kit + * SVT- Added new module that can verify secure configuration/usage of Logic Apps. +### Improvements/Fixes: +* Subscription Security + * Alert/ARM Policy enhancements + * Added capability to get alerts for ARM policy violations. However, we also found that a lot of internal (background) activity from Azure causes the alerts to get activated. We have disabled the alert for the while and will share feedback with PG. + * The alert module now runs against policy/rules stored in a central location (in a "read-only" storage blob inside an ISRM subscription). The benefit of this is that rules can be enhanced without needing to re-download/install the Dev Ops kit. + * Other small improvements about package setup, warnings text, etc. +* SS-Health - + * Added a new check to cover use of service principals across resource groups. This will help contain the risk from using a DevTest principal in a Prod RG and vice versa. + * Added support for remediating/correcting issues flagged in the RBAC health checks. + +* Dev/CICD Kit + * SVT enhancements + * Added more control check to the Service Fabric SVT module + * Renamed SVT report columns to be more intuitive + * Fixed issues reported in the App Service module + diff --git a/ReleaseNotes/RN161028.md b/ReleaseNotes/RN161028.md new file mode 100644 index 00000000..12e88b31 --- /dev/null +++ b/ReleaseNotes/RN161028.md @@ -0,0 +1,23 @@ +## 161028 +### New Features (preview): +* Simplified installation and update experience + * Fresh installation removes previous versions. + * Just a single cmdlet needs to be run after repo has been setup. +* Subscription Security + * N/A +* Dev/CICD Kit: + * SVT- + * Added new module that can verify secure configuration/usage of Storage. + * Security IntelliSense - + * Refactored sample demonstrating individual rules by feature area. + * Rules template definitions have been documented. Teams can start contributing new rules based on those templates now. + * All rules have been modified with complete descriptions and fix suggestions. +* Alerting & Monitoring: + * OMS-based "Application Security Dashboard" preview. + * Shows blades for subscription activity, activities grouped by function and activities corresponding to individual applications. + +### Feature improvements/fixes:? +* Subscription Security + * SS-Health - Skipped check for management cert if caller is non-Admin +* Dev/CICD Kit + * SVT enhancements - Fixed issues reported in the SQL module \ No newline at end of file diff --git a/ReleaseNotes/RN161111.md b/ReleaseNotes/RN161111.md new file mode 100644 index 00000000..8bfda449 --- /dev/null +++ b/ReleaseNotes/RN161111.md @@ -0,0 +1,23 @@ +## 161111 +### New Features: +* Subscription Security + * JEA server lockdown - PoC completed for locked down JEA jump-box. This is based on security baseline applied to WS-2016. A VHD is available if your team would like to try. +* Dev/CICD Kit: + * SVTs- + * Added new module for testing Logic App Connectors. +* Alerting & Monitoring: + * Completed a PoC for a sample "auto-remediation" scenario. An OMS-side alert notifies a configured email address and also (independently) triggers an automation via a web hook to "remediate" the situation. (We used "TDE got turned off " as the alert condition in our PoC). +We would love inputs from you for which scenarios to prioritize for "auto-remediation". + +* Central View of Control Coverage (PoC) + * Controls checked by various modules of the DevOps Kit are displayed here. This is a "live" feed because these same rules are also used by the DevOps kit scripts at runtime. +* Telemetry + * We have integrated telemetry support across all features in the DevOps kit. These will help us measure adoption, make quality improvements and also track the impact of the toolkit on risk reduction. + +### Feature improvements/fixes: +* Subscription Security + * SS-ASCConfig - Added a workarounds for a couple of PG limitations/issues ( [1] top level ASC policy changes are not percolating down to resource groups if prior policy exists at RG level and [2] even though contact details have been populated at the subscription policy level, ASC keeps warning about addressing the task). +* Dev/CICD Kit + * SVT enhancements - Significant improvements to the structure of PowerShell module output and logs. Also additional test cases added for some services (SQL, App Services). + * Refactored all SS-*/TCP-* SVTs to support centralized rules and standardized console display and log outputs. + diff --git a/ReleaseNotes/RN161125.md b/ReleaseNotes/RN161125.md new file mode 100644 index 00000000..ff3a93e2 --- /dev/null +++ b/ReleaseNotes/RN161125.md @@ -0,0 +1,31 @@ +## 161125 +### New Features: +* Subscription Security +* SS-Health: + * Central JSON-based provisioning and deprovisioning of central accounts for various roles and personas for subscription RBAC. +* JEA server lockdown: + * Validated and documented JEA server lockdown steps using WS-2016 R2 security baselines. (Note: We are still working to combine the standard 'lockdown' template with Code Integrity policies.) + +* Dev/CICD Kit: +* SVTs: + * Virtual Network Security - New (preview) module to test ExpressRoute-connected vNets (based on the new ARM-based myER solution) + * Significant improvements to SS-Health from an RBAC cleanup standpoint. (Based on a cross-team effort to identify the various accounts that ought to be there and ones that should be removed.) +* CICD/Build Integration: + * N/A + +* Alerting & Monitoring: + * None in this release. We are working on designing the core features for the per-Application OMS solution. + +* Telemetry: +* Preview of the telemetry dashboard for the DevOps kit. Give it a try here. + +* Central View of Control Coverage (PoC): +* Note: Controls checked by various modules (including the new ones added in this release) of the DevOps Kit are displayed here. This is a "live" feed because these same rules are also used by the DevOps kit scripts at runtime. + +### Feature improvements/fixes: +* Subscription Security: +* SS-Health: New checks for inclusion of pending alerts and recommendations from Azure Security Center (ASC) into the SS-Health output. +* SS-ASCConfig: Displays additional information about what the script does both on console and in logs. +* Dev/CICD Kit: +* SS-Health: Management certificates check now displays richer info about the certs. + \ No newline at end of file diff --git a/ReleaseNotes/RN161209.md b/ReleaseNotes/RN161209.md new file mode 100644 index 00000000..8610b715 --- /dev/null +++ b/ReleaseNotes/RN161209.md @@ -0,0 +1,41 @@ +## 161209 +### New Features: +* Subscription Security: +* SS-Health: + * We now check for configuration of ARM policy, resource locks and alerts in the subscription per ISRM expectations. (The ability to provision these already existed.) +* JEA server lockdown: + * Work for combining Windows Server 2016 Security Baseline templates and Code Integrity policy in a single image has been completed. +* SS-ARM Policy: + * ARM policy provisioning now supports policies that are deployed for ExpressRoute-connected virtual networks. +* Dev/CICD Kit: +* SVTs: + * Virtual Network Security - Enhanced the SVT for ExpressRoute-connected vNets with ancillary checks for the supporting infrastructure (presence of resource locks, ARM policies, alerts, etc.). The ER-Network SVT now also covers both corpnet and DMZ scenarios and checks for possible presence of multiple ER-connected vNets in the corresponding resource groups. + * Key Vault - Added core controls for checking Azure Key Vault instances. + * Logic App Connectors - Added controls for multiple commonly used Logic App Connectors to the Logic Apps SVT. +* Security IntelliSense: + * Added rules for coverage of traditional web application security issues (OWASP Top 10 category). Until now, SecIntel largely covered native Azure (PaaS API) and Crypto rules. + +* Continuous Compliance: +* Alerting & Monitoring: +* OMS - Completed work on PoC to run SVTs in a Automation Runbook and push the results into OMS. We already have SVTs running in VSO Build/Release steps. This gives us the core technical components we needed to make a complete OMS-based solution (target for next sprint!). + +* Common/Framework Components: +* New Names for Functions: + * Introduced easier to follow and naturally named 'aliases' for several current functions. These names are also compliant with PowerShell naming standards. (For e.g., Install-AzureRmISRMAlertsPkg is now aliased to Set-AzSDKAlerts). +This prepares us for a name change in the upcoming sprint release. + +* Central View of Control Coverage (PoC): + * Note: Controls checked by various modules (including the new ones added in this release) of the DevOps Kit are displayed on github. This is a "live" feed because these same rules are also used by the DevOps kit scripts at runtime. + +### Feature improvements/fixes: +* Subscription Security: +* SS-AlertsConfig: + * Added prioritization support for Azure Insights-based alerts. Only 'high' and 'critical' priority alerts are registered for email alerts. This should reduce the alert emails generated from the alerts setup. +* Dev/CICD Kit: +* None. + +* Common/Framework Components:? +* Control JSON Design: + * ControlIDs have been renamed with more intuitive names. (E.g., AzureStorage102 --> Azure_Storage_AuthZ_Use_SAS_for_Blob). Expanded the values for control evaluation status to cover a broader range of outcomes. +* Telemetry: + * Enhanced the telemetry dashboard to cover all the Pri-1 scenarios we were targeting for H1. Please give it a try here and let us know your thoughts! diff --git a/ReleaseNotes/RN161223.md b/ReleaseNotes/RN161223.md new file mode 100644 index 00000000..257fd012 --- /dev/null +++ b/ReleaseNotes/RN161223.md @@ -0,0 +1,60 @@ +## 161223 +### New Features: +* Subscription Security: + + N/A +* Dev/CICD Kit: + + N/A +* Build & Release Task for VSTS pipeline: + * SVTs can now be run in VSTS pipeline with all the different CICD workflow scenarios that are supported for custom tasks. + * We have published the 'Security Verification Tests' extension to the VSO extensions gallery and, further, have also submitted a request to get it added to 1ITVSO. In the interim, you can contact us to get the extension to try it out (or you can also download from the public gallery by searching for "Secure DevOps Extensions for Azure"). + * Additionally, SVT outcomes can be routed to an OMS workspace. +* SVTs: + * Virtual Machines - Added a net SVT to check core set of controls for Virtual Machines. + * Key Vault - Added additional controls for checking Azure Key Vault instances. +* Security IntelliSense: + * Added about 50+ new rules to cover various traditional AppSec secure coding concerns including a few advanced rules for Crypto. +? +* Continuous Compliance: +* Subscription Security - Continuous Compliance: + * We now have a runbook that can be deployed to your subscription and which can periodically scan the subscription against the SS-Health checks. + * The outcomes of these scans will get routed to an OMS workspace (with support for alerts for actions required). +* Application Security - Continuous Compliance: + * Similar to subscription security, application SVTs can be run in a runbook and route the outcomes to OMS. + +* Alerting & Monitoring: +* OMS Solution Pack for the DevOps Kit: + * This can be deployed to a target OMS workspace. It contains views, alert rules, alert schedules, etc. get unpacked into the workspace to form a complete "AzSDK Security Dashboard" for the team. + * The dashboard works against the OMS repository that is receiving events from various upstream DevOps kit components such as: + * Individual SVTs run by developers + * SVTs running in CICD pipelines + * SVTs running as part of Continuous Compliance runbooks), etc. + * Essentially, this creates the complete picture by adding alerting and monitoring support to continuous compliance. + +* Common/Framework Components: +* New Names for Functions: + * All aliases introduced in the last release have been converted to actual function names (and old names removed altogether as was notified in the cmdlet outputs in the last sprint). +* Telemetry + * Added support for exception display to the PowerBI dashboard. + +* Central View of Control Coverage (PoC): +* Controls checked by various modules (including the new ones added in this release) of the DevOps Kit are displayed here. This is a "live" feed because these same rules are also used by the DevOps kit scripts at runtime. + + +### Feature improvements/fixes: +* Subscription Security: +* SS-Health: + * We now check and discourage usage of custom RBAC roles. +* SS-ARMPol: + * Updated with more policy rules (audit classic resources and other non-HBI resource types) + +* Dev/CICD Kit: +* Made a validation pass for all SVTs against the most recent Azure PS modules/APIs for those service types. + +* Common/Framework Components: +* Control JSON Design: + * From 161209, ControlIDs have been renamed with more intuitive names. (E.g., AzureStorage102 --> Azure_Storage_AuthZ_Use_SAS_for_Blob). This makes displayed data more intuitive in several scenarios. +* Telemetry: + * Enhanced the telemetry dashboard to cover all the Pri-1 scenarios we were targeting for H1. Please give it a try here and let us know your thoughts! + \ No newline at end of file diff --git a/ReleaseNotes/RN170127.md b/ReleaseNotes/RN170127.md new file mode 100644 index 00000000..67399831 --- /dev/null +++ b/ReleaseNotes/RN170127.md @@ -0,0 +1,16 @@ +## 170127 +### Feature updates +* SVTs now support multiple resource groups in a single evaluation +* Option to view CICD SVT outcomes in aggregate form as opposed to individual failures +* CICD build task is now available in VSTS for internal projects +* Continuous Compliance runbooks support sending data to a common OMS workspace +* Application Continuous Compliance view in OMS available for preview +* New SVT for Virtual Networks. +* Added EULA and Privacy disclosure link in setup. + +### Other improvements/bug fixes +* SQL Firewall - added check for 'any-to-any' rule. +* Virtual Machines - added checks for RDP and WinRM ports on NSGs for a VM +* App Services - added check for WEB_SITE_LOAD_CERTIFICATES to flag loading all certs to the app service instance. +* Added option to use 'preview' modules of AzSDK for CICD Release Task + \ No newline at end of file diff --git a/ReleaseNotes/RN170223.md b/ReleaseNotes/RN170223.md new file mode 100644 index 00000000..25525c14 --- /dev/null +++ b/ReleaseNotes/RN170223.md @@ -0,0 +1,18 @@ +## 170223  +  +### Feature updates   +* New version of VSTS task to support multiple resource groups for application scans.  +* New SVTs for Azure Analysis Service, Azure Batch.  +* New PowerBI dashboard in preparation for per-BU telemetry views.  +* Continuous Compliance runbooks are now supported via the Scheduler Service.  +* Preview of 'Recommendation' feature in DevOps Kit OMS events for subscription security checks  +* Preview of a 'single command' installation experience for the DevOps Kit.  +  +  +### Other improvements/bug fixes  +* Mitigated issue from direct dependency on Graph API access for SVTs in CICD and runbooks. Basically the Azure PS module for Graph API has a bug where it does not work correctly while running as an SPN even if correct permissions are granted.   +* Fixed a bug where we were scanning all databases within a SQL server but showing output for only the last one.  +* Updated AppService backup feature control to align with a PG change to the backup API signature.  +* Corrected implementation for firewall IP ranges to address 'any to any' use case for ADLS and Vnets as well.  +* Added exceptions for presence of a couple of management certificates that are required for central services such as ARM-ER deployment.  +  \ No newline at end of file diff --git a/ReleaseNotes/RN170331.md b/ReleaseNotes/RN170331.md new file mode 100644 index 00000000..c33aa41a --- /dev/null +++ b/ReleaseNotes/RN170331.md @@ -0,0 +1,18 @@ +## 170331  +  +### Feature updates   +* Introduced capability to target specific controls and service types in security scans  + * Controls can be scanned by tags (e.g., controls tagged with "SOX")  + * Controls can be scanned for specific service type (e.g., "all SQL DBs" in a subscription)  +* Unified master command to perform all requested scans (subscription, service types) and generate a single report.  +* Security IntelliSense augmented to support flagging security issues in XML files (e.g., web.config).  +* Redesigned output folder hierarchy with much shorter overall path length (moved to a folder under %LocalAppData%).  +* The output LOG/CSV folder is now auto-opened upon completion for user convenience. We also have a friendly README.txt in the opened folder to describe what to do next.  +  +### Other improvements/bug fixes  +* Began migration of the DevOps Kit PS modules to a 'class'-based design (introduced in PowerShell 5.x.). This new v2 architecture makes it significantly easier to add new service SVTs.  +* Refactored to support a pub-sub model  makes plugging in other components (such as event listeners) easy.   +* Running subscription security checks now require only 'Reader' permissions on the subscription.  +* Added support for scanning 'classic' resource types in subscription security check.   +* Fixed an issue in the installer pre-requisite check. Dev Ops Kit now works even if multiple Azure PowerShell versions are present (so long as the default version used is compatible).  +  \ No newline at end of file diff --git a/ReleaseNotes/RN170428.md b/ReleaseNotes/RN170428.md new file mode 100644 index 00000000..934e2092 --- /dev/null +++ b/ReleaseNotes/RN170428.md @@ -0,0 +1,18 @@ +## 170428  +  +### Feature updates   +* Added security verification tests (SVTs) for Azure CDN and Redis Cache.   +* Added support for 'Fix Recommendation' feature across all service types. This will help users resolve control failures rapidly.  +* Added support for scanning Cloud Services (classic). (Although the kit is primarily ARM-focused, several teams had requested an SVT for classic Cloud Services.)  +* Enhanced VM SVT to scan a baseline set of controls for Linux VMs.  +* Added support for validating specific controls (by control-id) in SVTs. This allows checking for specific controls such as ‘encryption-at-rest’ across all resources of a specified type.  +* Enhanced the telemetry dashboard with targeted views for BU stakeholders containing more intuitive display charts and metrics.  +  +### Other improvements/bug fixes  +* Completed migration of all DevOps Kit modules to PowerShell 5.0+ class-based design.   +* Fully separated organization-specific configuration settings from control JSONs.   +* Added ability to set level of detail in telemetry (none, anonymous, full) and to separate telemetry by type of event (API v. usage v. control evaluation).  +* Completed security (SDL), privacy and red team penetration testing reviews for the devops kit project.  +* Refactored runtime components to better isolate control evaluation results database.  +* Added ability to 'bootstrap' the DevOps kit for specific environments.  +* Fixed issues in ASC config validation and Forensics module.  \ No newline at end of file diff --git a/ReleaseNotes/RN170531.md b/ReleaseNotes/RN170531.md new file mode 100644 index 00000000..c2f3c725 --- /dev/null +++ b/ReleaseNotes/RN170531.md @@ -0,0 +1,21 @@ +## 170531  +  +### Feature updates  +* Support for tracking control attestation state across the SVTs. The DevOps Kit now allows for and honors user overrides of raw control status. This is to enable scenarios such as:  + * "I want to testify that the outputs for a control marked 'Verify' have been reviewed and should be 'treated as Passed'"  + * "I want to override the status of a control marked 'Failed' and treat it as 'Passed' because the risk is low given other contextual information for my scenario"  + * "I want to acknowledge the risk for a control marked 'Failed' and treat it as an 'Exception' for now"  +* All controls now have a 'Severity' field to help teams distinguish issues by degree of risk.  +* Added a unified command to scan a subscription and resources for SOX compliance and generate a report that can be leveraged by a SOX auditor.  +* Added security verification tests (SVTs) for On-premise Data Gateway (ODG) and Azure Traffic Manager.  +* Added support for versioning control-JSONs used by SVTs. This will alleviate backward compat issues and ensure that cmdlets from a particular version of the DevOps Kit pick up corresponding versions of control JSON to run against.   +  +### Other improvements/bug fixes  +* Fixes to Continuous Assurance framework and runbook:   + a) A Get-AzSDKContinuousAssurance cmdlet to provide a summary of the current CA setup/configuration in the subscription  + b) A Remove-AzSDKContinuousAssurance cmdlet to cleanup CA setup  + c) Fixed an issue due to which CA runbook was switching into 'offline' mode due to an encoding issue of the serverUrl  +* Added progress updates in the PS console display to indicate overall scan completion status. This should help in long-running scans involving a large number of resources.  +* Removed some SQL Server (VM) based controls that had been included in the Azure SQL DB SVT.   +* All DevOps Kit docs have been moved to Markdown (MD) format from OneNote. This will help improve user navigation experience and will also give better versioning/change control support. The root doc is now hosted at MSIT Wiki and thus accessible to all without having to join a group.  +* Fixed an issue in the CICD extension which was causing an exception at the end of the pipeline.  diff --git a/ReleaseNotes/RN170630.md b/ReleaseNotes/RN170630.md new file mode 100644 index 00000000..738793e1 --- /dev/null +++ b/ReleaseNotes/RN170630.md @@ -0,0 +1,24 @@ +## 170630  +  +### Feature updates  +* [Control attestation](https://azsk.azurewebsites.net/00c-Addressing-Control-Failures/Readme.html#starting-attestation) for 'stateful' controls to facilitate scenarios that require manual state verification. For example, for controls such as:  + * "Are these the correct members in the Owners role for this resource? "  + * "Is the list of IP addresses configured on the DB firewall correct?"  +For all such controls, DevOps Kit now stores the 'attested state' and resets the status back to 'Verify' if there is any 'drift' from that state. (E.g., if another person is added to the said role or a new IP address is added on the firewall.) This basically makes 'continuous assurance' even more meaningful.  +* An improved [OMS solution](https://azsk.azurewebsites.net/05-Alerting-and-Monitoring/Readme.html#setting-up-the-azsk-oms-solution-step-by-step):  + * The solution setup is much simpler (one-pass setup, requires minimal user inputs, no JSON editing, etc.)   + * Richer set of out-of-box/ready-to-use artifacts for ops teams including:  + * A unified view capturing subscription security, enterprise network security and application (RGs) security  + * Several built-in 'searches' on top of AzSDK control evaluation events  + * Pre-configured alerts for the important/actionable items  +* A (preview) UI for the DevOps Kit. +* DevOps Kit now supports AzureRm 4.x PowerShell modules. (The required version of AzureRm is automatically installed by DevOps Kit setup/update command.) Refer [link](https://azsk.azurewebsites.net/00a-Setup/Readme.html) +* Support for downstream integration - AzSDK now supports sending events to an Event Hub and a generic Webhook. Both of these enable scenarios where control evaluation events can be routed to other repositories (besides OMS).  +* Added security verification tests (SVTs) for Azure Automation, [Cosmos DB](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/Feature/CosmosDB.html) (Document DB) and [Stream Analytics](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/Feature/StreamAnalytics.html).  +* Significantly enhanced AzSDK Telemetry views and deployed an RBAC model for individual BU/SL leads to get access to their telemetry views.   +  +  +### Other improvements/bug fixes  +* Improved [Continuous Assurance setup](https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#setting-up-continuous-assurance---step-by-step). Users need not provide an AzureADAppName parameter any more. AzSDK internally creates an Azure AD app on behalf of the user. (Note that this AAD app/SPN is used as the runtime account for scanning.)  +* Made the phone number parameter mandatory in [Set-AzSDKSubscriptionSecurity](https://azsk.azurewebsites.net/01-Subscription-Security/Readme.html#setup-azure-security-center-asc-on-your-subscription). This is used to set the security point of contact in ASC and was (accidentally left as) optional earlier.  +* Completed preparatory work to retire the TCPs site (http://aka.ms/azsdktcp). These will be directly available in the core documentation.   diff --git a/ReleaseNotes/RN170731.md b/ReleaseNotes/RN170731.md new file mode 100644 index 00000000..65676f18 --- /dev/null +++ b/ReleaseNotes/RN170731.md @@ -0,0 +1,22 @@ +## 170731  +  +### Feature updates  +* Installer - Resource providers needed are auto-registered. Improved handling of clashes due to multiple versions of AzureRm PS modules  +* Subscription Security - support for automated removal of 'deprecated' accounts   +* Added security verification tests (SVTs) for Azure Load Balancer service  +* Continuous Assurance:   + * Get-CA cmdlet updated to perform a deep diagnosis of defunct CA setups  + * Elaborate guidance for users at the end of Install-CA  +* Support for generating output reports in PDF format (for auditing scenarios)  +* PoC to support AzSDK SVTs in CICD for Jenkins  + (Preview) Support for activity log alerts using action groups  +  +### Other improvements/bug fixes  +* Split VM controls to separate status of anti-malware, disk encryption, patched state, etc.  +* ASC tasks/recommendations - only 'active' ones to result in control failure ('dismissed' ones are now filtered out). We can now control which subset of ASC recommendations are to be treated as required org-wide.  +* ASC - consistent handling of email & phone. The values provided will always overwrite current settings.  +* Added cmdlet-acronym at end of output logs folder for easier identification of folders corresponding to past runs ("20170801_005414_UCA" <- Update-AzSDKContinuousAssurance, "20170731_231345_GSS" <- Get-AzSDKSubscriptionSecurity,  etc.)  +* Storage SVT - added new control check to enforce HTTPS endpoint on storage accounts  +* Added some custom RBAC roles and ER-mgmt certs to whitelist. Also, approved SPNs will not be flagged as objectionable.  +* Moved ACI, SDO Analytics and Cloud Cruiser related accounts to 'deprecated' list.  +  \ No newline at end of file diff --git a/ReleaseNotes/RN170831.md b/ReleaseNotes/RN170831.md new file mode 100644 index 00000000..d4737a1c --- /dev/null +++ b/ReleaseNotes/RN170831.md @@ -0,0 +1,17 @@ +  +## 170831  +  +### Feature updates  +* Support for 'baseline mode' for AzSDK scans. In 'baseline mode' a centrally defined 'control baseline' is used as the target control set to scan. This mode can be centrally configured as the default behavior for CA scans. Moreover, for manually validating conformance, this can also be passed as a switch to the scan commands.   +* A new OMS view showing subscription, ERNetwork and resource security status. The view has lots of usability improvements and should make it easy to review and resolve baseline control failures for various resource types.  +* New SVTs added for Azure Functions.  +* A preview of the 'fix controls' feature. This mode can be triggered via a "-GenerateFixScript" switch in the scan commands and makes AzSDK generate automated fix scripts for a subset of failed controls. These scripts can be subsequently run to rapidly remediate such controls.  +* The Get-AzSDKAzureServicesSecurityStatus now supports checkpointing via a "-UsePartialCommits" switch. When this switch is used, the command periodically persists scan progress to disk. That way, if the scan is interrupted or an error occurs, a future retry can resume from the last saved state. This capability also helps in CA scans where Azure forcefully suspends 'long running' automation jobs.  +* The CA runbook has been enhanced with various telemetry capabilities. For instance, it can now track the delta between resources present in a subscription v. resources actually scanned via CA. For virtual machines, we have also added metadata to get VM type, whether a VM is on an Express Route circuit or not, etc.   +  +### Other improvements/bug fixes  +* Added support to scan (classic/ASM) Cloud Services with ARM Reader privilege. This allows us to bring them in scope for CA scans.  +* Control attestation now supports different expiry intervals based on severity. Expiry periods can be set in the backend configuration.   +* Updated the PDF report generator to also include control attestation data.   +* The list of deprecated/'white-listed' central accounts has been updated.  +* The aka.ms/azsdktcp and aka.ms/azsdkosstcp AzSDK control info sites have been decommissioned. The content has been moved to GitHub diff --git a/ReleaseNotes/RN170928.md b/ReleaseNotes/RN170928.md new file mode 100644 index 00000000..37f39552 --- /dev/null +++ b/ReleaseNotes/RN170928.md @@ -0,0 +1,16 @@ +## 170928  +  +### Feature updates  +* Migrated AzSDK alerts to use the [new Azure PG alert framework](https://azsk.azurewebsites.net/01-Subscription-Security/Readme.html#azsk-subscription-activity-alerts-1) which offers more powerful alert targeting using 'Action Groups'. The older mechanism of activity alerts has been deprecated (by PG). (See next point about how we will migrate everyone to the new approach.)  +* Added a new cmdlet [(Update-AzSDKSubscriptionSecurity)](https://azsk.azurewebsites.net/01-Subscription-Security/Readme.html#update-subscription-security-baseline-configuration) to serve as a single command to ensure all important artifacts such as Alerts, ASC, ARM Policy, RBAC and Continuous Assurance runbook can be updated in one go to match the latest. This will allow teams to keep their subscriptions in sync with the latest security features of Azure and also stay aligned with CSE-wide policy/config changes.   +* [(Preview) Continuous Assurance now supports a 'central scan' mode.](https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#continuous-assurance-ca---central-scan-mode) This will enable central teams to setup CA in a 'master subscription' and scan an entire group of target subscriptions. Please contact us if you'd like to try this out.  +* A ["Rationale" field](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/README.html) has been added to all the 260+ controls across AzSDK. This field covers the "why" aspect of the control and helps a user understand security risks better.  +* The ["fix controls"](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/README.html) feature has been extended to most of the controls for key services (AppService, Azure SQL DB, Storage, VMs, etc.). More services will be covered in future sprints.  +  +### Other improvements/bug fixes  +* You can now generate reports at a location of your choice (e.g., Desktop) using the [Set-AzSDKUserPreference](https://azsk.azurewebsites.net/00b-Getting-Started/Readme.html#complete-list-of-azsk-commands) command.   +* Scan commands now output a brief summary table about controls evaluated.   +* The telemetry dashboard has been enhanced in prep for Wave-2. More views have been added for LT.  +* Docs: A major overhaul of [Alerting & Monitoring page](https://azsk.azurewebsites.net/05-Alerting-and-Monitoring/Readme.html) to cover setup and use of the latest OMS solution.  +* Docs: Added a [summary table for all AzSDK cmdlets](https://azsk.azurewebsites.net/00b-Getting-Started/Readme.html#complete-list-of-azsk-commands), coverage for "-FixControls" and "-UseBaselineControls" flags.  +* Controls: Modified VM controls to distinguish "ER-connected" VM v. not, changed Storage-GRS to 'Verify', added [new controls for Data Factory](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/Feature/DataFactory.html) DMG features, etc.  diff --git a/ReleaseNotes/RN171031.md b/ReleaseNotes/RN171031.md new file mode 100644 index 00000000..81d4edf3 --- /dev/null +++ b/ReleaseNotes/RN171031.md @@ -0,0 +1,36 @@ +## 171031  +  +### Feature updates  +* Support for bulk-attestation. For scenarios where several resources that have a specific control that needs to be attested (e.g., several storage accounts have logging turned off), one can now run attestation in 'bulk' mode and target all resources.  +* Continuous Assurance (CA) Central Scan mode:   + * Enhanced to support side-by-side scanning with individual-mode CA setups.   + * Added support for flag to store logs in central subscription or individual subscriptions.  + * Update-CA can handle updating target subscriptions list for central CA.  +* Continuous Assurance:  + * Logs are now retained in the subscription for a maximum of 30 days (in the storage account within AzSDKRG).  + * Get-AzSDKContinuousAssurance now supports quick v. exhaustive diagnostic checks. Module health and related time-consuming checks are done only if the '-ExhaustiveCheck' flag is specified. (This saves time for scenarios such as when a user just want to do some basic diagnosis or query for a specific CA config setting.)  +* Security IntelliSense: Support for security checks in XML (config) files is now included as part of the extension.  +* Org Config - Reduced the default configuration footprint required for standalone AzSDK setup for organizations. Also, default OMS settings can now be configured at organization scope. These changes make it easier for other orgs to quickly adopt and start using AzSDK.  +* (Preview) ARM-template security checker. Ability to scan ARM-templates for AzSDK controls. This helps by getting security coverage into pre-deployment stage. Please get in touch with us if you'd like to try this out.  +  +### Other improvements/bug fixes  +* Installer:   + * The "iwr" installer now detects previous versions of AzSDK loaded in memory and warns the user to run in a new PS session. This was a common issue many people faced during upgrade.  +* SVTs:   + * A new column in AzSDK scan CSV files now helps users by pointing to respective detailed LOG file that can be used for understanding control failures better. Also, for cases when a control scan is skipped due to insufficient permissions, the 'Recommendation' text provides a clear indication of this.  + *Added support for comma-separated list of individual resource instances for the resource scan command. Similar to comma-separated resource groups, one can now pass a comma-separated list of individual resource names for scanning.  +* Controls:   + * Enhanced Storage account controls to respect different storage types (standard/premium/blob).  + * Enhanced Key Vault controls to better handle detection of use of old/expired keys.  +* Attestation workflow:  + * Attestation states have been refactored to reflect DSRE (GRCC) risk governance terminology better.   + * Also enabled expiry for  'NotAnIssue' state (set to 90 days as default) in keeping with typical entitlement review periods.  + * During interactive attestation, we now display detailed control state for the resource being attested.  +* Security IntelliSense: Supports VS 2017 editor now.   +* CICD Extension: Enabled support for Hosted-2017 agent pool.  +* Continuous Assurance (CA):  + * Improved recovery behavior of CA in case of modules-related failures (failed updates, missing modules).  +* Docs:   + * Added content to the 'Telemetry' / 'Risk Governance' sections.   + * Added summary of costs incurred for running AzSDK to CA docs (CA FAQ section).  + * Created a new document to speed up AzSDK learning curve for users new to PowerShell: (http://aka.ms/azsdkdocs/pstips)   \ No newline at end of file diff --git a/ReleaseNotes/RN171130.md b/ReleaseNotes/RN171130.md new file mode 100644 index 00000000..72695bed --- /dev/null +++ b/ReleaseNotes/RN171130.md @@ -0,0 +1,24 @@ +## 171130 (v.2.8.*) +### Feature updates +* We have introduced a metadata command 'Get-AzSDKInfo' that can be used to get rich information about the DevOps kit for a subscription. You can use this to get information such as: + * Version info about various artifacts + * Info about controls, current baseline controls, etc + * A summary of control attestations that have been done for the subscription. +* Auto-update support: From this release on, users can choose to configure auto-update for the DevOps kit. The first auto-update will actually happen from the next release. (Note that the DevOps kit always auto-updates in Continuous Assurance setups. This feature is for the PS module on your desktop.) +* AzSDK CICD Extension has been updated to support the complete set of parameters that are covered in manual scan (GRS) command. +* A preview of the new website for the DevOps Kit. Our intent is to make this the one place for DevOps Kit content (such as documents, videos, blogs, releases, news updates, etc.). +* A new command to quickly setup a standalone 'Organization policy' endpoint for the DevOps kit. This was possible earlier but needed a lot of manual steps (almost a day of work). The command can be used to create a org-specific installer, customize various DevOps Kit policies and behavior. Once the org policy server is set up, subscription users in the org can run manual scans, setup Continuous Assurance, create the OMS view, etc. Support for running the DevOps Kit CICD release extension with custom org policy shall be added in an upcoming sprint. + +### Other improvements/bug fixes +* Installation: + * Added EULA & Privacy Disclosure support. (You will have to accept it once and the kit will remember it.) + * DevOps kit will now force refuse to run scan commands if the version is older than 'N-2' where N is the current version. This ensures that the set of controls checked and the underlying logic is recent enough. +* SVTs: + * The scan commands now send additional metadata that will help the backend better evaluate the 'acceptability' of a control status event (from manual scans) for central compliance metrics. This includes things like additional metadata about resource type, user RBAC permissions, attestation access, etc. +* Controls: + * Fixed issues related to RDP control status for Cloud Services. + * Added support for the recently released product feature to set 'HttpsOnly' for AppService & Azure Functions. + * For VMs in deallocated state, control checks for anti-malware and OS patching have been changed to directly reflect Azure Security Center status. +* Attestation: + * Fixed an issue about Owner not able to attest. Running Update-AzSDKSubscriptionSecurity will create any core DevOps Kit resources that are not present/got deleted accidentally. + diff --git a/ReleaseNotes/RN180115.md b/ReleaseNotes/RN180115.md new file mode 100644 index 00000000..fa4a0c1f --- /dev/null +++ b/ReleaseNotes/RN180115.md @@ -0,0 +1,38 @@ +## 180115 (v.2.9.*) +### Feature updates + +* The DevOps Kit PowerShell module will be renamed from 'AzSDK' to 'AzSK' in an upcoming release. As a first step towards that, aliases have been introduced for the commands. (Existing names will continue to work for the time being.) +* [Continuous Assurance:](https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#setting-up-continuous-assurance---step-by-step) + * CA can now be setup to send events to 2 different OMS workspaces. This provides a service group the ability to use a common workspace for viewing CA status across multiple service subscriptions (while individual dev ops teams can continue to use their own OMS workspaces for monitoring). + * Added support for specifying a webhook in CA setup to facilitate downstream extensibility scenarios. + * CA scan interval is now configurable. It can be set at an org or individual setup level. (The default is 24 hrs.) + * The parallel-CA scanning feature has been enhanced to [(a) support appending to existing target subscriptions and (b) central logging with subscription id as parent folder,](https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#1-central-scan-mode-ca-using-a-single-automation-account-default-behavior) [(c) Get-CA has been made 'central-scan' mode aware (will emit central scanning setup info)](https://azsk.azurewebsites.net/04-Continous-Assurance/Readme.html#1-central-scan-mode-ca-using-a-single-automation-account-default-behavior). +* OMS + * If local OMS settings are not explicitly configured, local scans will attempt to leverage the OMS settings from the CA configuration for the subscription. (This can alleviate the need for individuals to explicitly configure local redirection.) +* ['Compliant' ARM Templates (Preview)](../ARMTemplates) + * We are including ARM templates for various resources which can be used as reference when creating your own templates. These 'compliant' templates have been created after passing applicable AzSDK controls for corresponding resources. Looking forward to early adopters/feedback. You can download from http://aka.ms/azsk/armtemplates. +* [ARM Template Checker (Preview)](https://azsk.azurewebsites.net/03-Security-In-CICD/Readme.html#azsk-arm-template-checker) + * We have created a VSTS extension that can run the DevOps Kit ARM Template Checker in the CICD pipeline. (The 'ARM Template Checker' provides an ability to scan ARM templates directly as opposed to the default AzSDK scanning which happens against deployed resources). This extension will provide us the ability to deny creation of non-compliant ARM resources out of the box. + +### Other improvements/bug fixes +* SVTs: + * Subscription and Resource Scan checks will now also perform a lightweight "is CA correctly setup?" check at the start of the command. + * Fixed a regression in the "-GenerateFixScript" feature. +* Controls: + * New controls added for App Service, Key Vault, Storage based on recent feature improvements from the product team. + * Fixed an issue with RDP-related control check in CloudService SVT + * A couple of controls have been removed from Storage: (a) GRS and (b) alerts for anonymous access. We are working with PG to get some clarifications for both + * [New ARM policy has been introduced to support denying creation of classic resources.](https://azsk.azurewebsites.net/02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.html) +* Get-AzSDKInfo command: + * Improved UX for various queries (ControlInfo, BasicInfo, etc.) + * Fixed a performance issue for the AttestationInfo option. +* Attestation: + * Fixed a couple of issues where in absence of additional constraints/checks an attestation was applying to a broader scope than desired. + +* CA: + * Get-CA will now check that runbook version is up to date and, also, warn if there are resource locks on AzSDKRG. + +* CICD: + * Implemented a workaround for a PG issue for our CICD extension that was resulting in SAS-token-based policy access to fail. + + diff --git a/ReleaseNotes/RN180215.md b/ReleaseNotes/RN180215.md new file mode 100644 index 00000000..93c40c76 --- /dev/null +++ b/ReleaseNotes/RN180215.md @@ -0,0 +1,27 @@ +## 180215 (v.2.10.* ) +### Feature updates + +* DevOps Kit Configuration Checks: + * We have introduced a [set of controls that will validate the DevOps Kit setup and configuration for a given subscription as part of scans](https://github.com/azsk/DevOpsKit-docs/blob/master/02-Secure-Development/ControlCoverage/Feature/AzSKCfg.md). These will proactively inform users about things such as (a) broken CA setups, (b) older version of the DevOps Kit module, (c) CA runbook too old, etc. + * These ‘DevOps Kit health’ control results will also be sent to OMS. +* Activity Alert Monitoring: + * Added central visibility to activity log alerts. This will get us telemetry on how frequently alerts are firing across subs and help enrich them. + * Added capability to register for receiving [SMS alerts for role assignment alerts.](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#configure-alerts-for-your-subscription) +* OMS: + * [We have enhanced the OMS solution queries](https://github.com/azsk/DevOpsKit-docs/blob/master/05-Alerting-and-Monitoring/Readme.md#guide-to-azsk-oms-solution-queries) by leveraging richer metadata that is sent to OMS + +### Other improvements/bug fixes +* AzureRm 5.2 + * Migrated the DevOps Kit to use AzureRm 5.2.0 instead of AzureRm 4.1.0. This will be automatically installed as part of upgrade (in all scenarios SDL, CICD, CA). +* Renaming AzSDK -> AzSK: + * The CICD release extension has been republished with the changed module name. More (internal) work in progress for the overall renaming effort. +* Controls: + * Function Apps – fixed HTTPS/AuthN controls to apply only if trigger = HTTPS. + * Cloud Service – fixed a control issue when the cloud service has no config settings. + * Fixed other issues observed from errors/exceptions via our telemetry. +* CA: + * Simplified the experience for CA SPN cert renewal via a [‘-RenewCertificate’ switch in Update-CA](https://github.com/azsk/DevOpsKit-docs/tree/master/04-Continous-Assurance#updating-an-existing-continuous-assurance-setup). + * Added more diagnostic info to help troubleshoot runbook issues. + * Local scans will start respecting AltOMSworkspace as well. +* CICD: + * Updated our CICD release extension to use the latest VSTS Task SDK. diff --git a/ReleaseNotes/RN180315.md b/ReleaseNotes/RN180315.md new file mode 100644 index 00000000..2c1d1b44 --- /dev/null +++ b/ReleaseNotes/RN180315.md @@ -0,0 +1,37 @@ +## 180315 (AzSK v.3.0.* and AzSDK v.2.11.*) +### Feature updates + +DevOps Kit Module Migration: + * We are releasing *two* PS modules in this release - AzSDK.PS1 (v 2.11.x) and AzSK.PS1 (v 3.0.x). + * To use the new AzSK module, subscriptions will need to be migrated from "AzSDK" to "AzSK" (in terms of naming of various artifacts created and used by the DevOps Kit such as alerts, automation account, storage account, policy, etc.). + * Old ‘Get/Set-AzSDKxxx’ commands are supported only in the old (AzSDK) module and new commands ‘Get/Set-AzSKxxx’ in the new (AzSK) module. + * Until the subscription is migrated, the 'old' AzSDK module (with 'AzSDK' version of cmdlets) should be used. + * Once a subscription has been migrated, cmdlets from the new module should be used. + * Note that the migration impacts all of these scenarios: + * Ad hoc/local scans from PS sessions (including local settings/log folders, etc.) + * Continuous Assurance + * CICD Release Task + * OMS Solution for monitoring + * Migration is easy! After the new AzSK module is installed, you just need to run ‘Update-AzSKSubscriptionSecurity -SubscriptionId -Migrate’ + +>Note: "If you have setup org-policy using the Install-AzSDKOrganizationPolicy cmdlet, please do not migrate your subscriptions yet. See [https://aka.ms/devopskit/extmigration](https://aka.ms/devopskit/extmigration) ." + +### Other improvements/bug fixes + +* AzureRm 5.2 + * We have fixed an important issue that was earlier causing conflicts between AzureRm 4.x and 5.x on users' machines. (After this change, the DevOps Kit module will list explicit dependencies on individual AzureRm modules.) +* SVTs: + * Fixed an issue that was causing resources scans (GRS) to not complete due to inclusion of 'non-supported' resource types in the 'resources-to-scan' list while using ‘checkpoint’ mode. +* Controls: + * Cloud Service – fixed a control issue when the cloud service has no config settings. + * CORS control check is skipped for ‘Premium’ storage (which does not support CORS). + * PIM - new control added to test if PIM has been enabled on a subscription. +* CA: + * Local scans will start sending events also to a secondary OMS workspace if one is configured in CA. + * Fixed an issue in the implementation of Webhook listener. This was earlier causing failures while sending events to Webhook in both ad hoc scans and from CA. +* OMS: + * Support for old (pre-Kusto) OMS view has been removed. + * Attestation expiry date is also included in control scan events sent to OMS. +* CICD: + * Updated CICD release extension to support the transition from old module to the new one (‘AzSK’). + diff --git a/ReleaseNotes/RN180416.md b/ReleaseNotes/RN180416.md new file mode 100644 index 00000000..35dcde69 --- /dev/null +++ b/ReleaseNotes/RN180416.md @@ -0,0 +1,47 @@ +## 180416 (AzSK v.3.1.*) +### Feature updates + +DevOps Kit Module Migration: +* We have completed all the core tasks vis-a-vis migration from AzSDK to AzSK. +* This release only ships the "AzSK" module. +* If your subscription is not migrated yet, you can still do it. Just run ‘Update-AzSKSubscriptionSecurity -SubscriptionId -Migrate’ + +Org-policy feature updates: +* Customers who were managing their own org-specific DevOps Kit policy can now migrate the "AzSDK-based" policy to "AzSK" using the "Update-AzSKOrganizationPolicy" cmdlet with the "-migrate" switch. +* The core DevOps Kit resources (names, location) can be more explicitly controlled by such organizations. + +ARM Template Checker: + * The ARM Template Checker has been integrated into the DevOps Kit. It can be invoked using the "Get-AzSKARMTemplateSecurityStatus" cmdlet. The cmdlet can check templates for App Service, Storage, SQL, CDN, Traffic Manager, Document DB, Redis Cache, Data Lake. +* The ARM Template Checker is also available in the VS Gallery as a CICD extension. + +Multi-subscription (or 'Central Mode') CA Scanning: + * This feature has been augmented to support load-balancing the overall set of subscriptions amongst multiple automation accounts in the master subscription. This capability should unblock some customers who were facing scale challenges due to Azure Automation limitations. The feature should also work more robustly side-by-side with 'individual scan' mode. + +Command Shortcuts: +* Most DevOps Kit cmdlets can now also be invoked using their 3-letter acronyms (e.g., 'grs' for 'Get-AzSKSubscriptionSecurityStatus', 'ica' for 'Install-AzSKContinuousAssurance', etc.). Short names are also supported for common parameters (e.g., 'gca -s {sub-id}' for 'Get-AzSKContinuousAssurance -SubscriptionId {sub-id}'). + +Public Git Repo: +* The DevOps Kit source repo (with AzSK-based code) is at: https://github.com/azsk/DevOpsKit +* The documentation is at: https://github.com/azsk/DevOpsKit-docs + + +### Other improvements/bug fixes + +SVTs: + * We have optimized the backend calls to AI-telemetry. This should improve scan command execution times by up to 50% in most cases. + +Controls: +* VM patching and vulnerability controls have been updated to use a new approach per recommendation from the ASC team. +* Fixed an issue related to cloud service controls getting triggered for classic VMs. +* HttpsOnly control fix can be generated using the ‘-GenerateFixScript’ flag when scanning. +* ERVNet SVTs were failing for some VMs due to auto-created VM NICs (which were not accessible through the Azure portal). The SVTs will now filter such NICs out. + +CA: +* A special 'scan-started' and 'scan-completed' event has been introduced in CA. This will be sent to OMS currently. + + +CICD: +* The CICD release extension now includes both the ARM Template Checker and the Security Verification Tests (SVTs) extensions. + + + diff --git a/ReleaseNotes/RN180515.md b/ReleaseNotes/RN180515.md new file mode 100644 index 00000000..480d1c94 --- /dev/null +++ b/ReleaseNotes/RN180515.md @@ -0,0 +1,41 @@ +## 180515 (AzSK v.3.2.*) +### Feature updates + +ARM Template Checker: +* Added the ability to exempt specific checks from ARM template scans and also exclude specific files from a scan folder. This provides teams fine-grained control when using the tool in CICD pipelines. + +AzSK PS Session Reset: +* Added the ability to reset AzSK session state. This will reduce the need to close and reopen PS console session in several common situations (thus saving time from having to login, etc.) +* This can be invoked via ‘Clear-AzSKSessionState’ (or simply the acronym: 'css') + +Security Verification Tests (SVTs): +* Preview controls are now available for Bot Service and Container Instances. + +Org-policy feature updates (non-CSE): +* Non-CSE customers using org policy feature can now get a view of AzSK health across the organization through a custom dashboard that is created at org policy setup time and deployed to the policy host subscription. +* Org policy owners can also control *when* users across the org will start using a new release of the DevOps Kit. This setting is included in the AzSK.Pre.json file in the 'policies' container. **Impt:** At present, org policy owners have to explicitly update this setting upon each DevOps Kit release. +* The CA runbook and associated scripts have been extensively commented and instrumented with the goal of quicker diagnosis in various scan setup scenarios (central mode, multi-CA, etc.) +* The AzSK PS Session Reset feature can be used to rapidly test org policy changes without having to restart PS each time. + + + +### Other improvements/bug fixes + +SVTs: + +* Following through on perf work from last sprint, we optimized calls to Event Hub and Webhook by batching multiple calls. +* Fixed an issue in attestation which was causing indexing conflicts when reading attestation data. + +Controls: +* Removed encryption controls from Storage Files & Queues (these are enabled by default in the product now). +* Fixed a couple of issues related to ASC configuration check control. + +CA: +* The CA runbook and supporting scripts that run during a CA scan have been augmented to emit significantly more diagnostic information. This will speed up diagnosis of CA scan issues. +* Fixed an issue whereby, upon an error during CA setup, the 'rollback code' was deleting a user-provided SPN. We now do not delete SPNs if they were explicitly passed to the CA commands. + +CICD: +* Fixed an issue related to default folder path when using ARM Checker in CICD. + + + diff --git a/ReleaseNotes/RN180618.md b/ReleaseNotes/RN180618.md new file mode 100644 index 00000000..ddb5466d --- /dev/null +++ b/ReleaseNotes/RN180618.md @@ -0,0 +1,76 @@ +## 180618 (AzSKPreview v.3.3.*) +#### Important Note: + +This time we are releasing only a preview version of the DevOps Kit. +To try out the preview features, use the following steps: + +In a new PS session, run: +```PowerShell +Install-Module AzSKPreview +``` +In a new PS session, run the below command before running any AzSK commands. +```PowerShell +Import-Module AzSKPreview +``` + +### Feature updates + +DevOps Kit Module Migration: +* All tasks for migration from AzSDK -> AzSK have been completed. Support for migration shall be discontinued from this release. +* Moving forward AzSK commands will delete AzSDKRG (older resource group) if the caller has sufficient privilege to do so + +Security Verification Tests (SVTs): +* Completed control implementation for Bot Service and Container Instances. + +Attestation Workflow Changes: +* Ability to mark certain controls as "not attestable" and, also, to specify permissible attestation states for others. +* Split "NotAnIssue" (which had an overloaded meaning earlier) into the following 3 possible states: +* (Genuine) NotAnIssue -- to represent situations where the control is implemented in another way, so the finding does not apply. +* StateConfirmed -- to represent acknowledgment by a user that the control state (e.g., IP addressed ranges on a firewall) is correct/appropriate +* NotApplicable -- the control is NA for the given design/context (e.g., a storage container that is public access ‘by design’) + +Cmdlet to generate a compliance summary (preview): +* Ability to list the current (latest) view of all controls from a compliance standpoint. +* Currently this will need to be locally enabled. (In the next sprint we will work on updating the compliance snapshot also from CA/CICD.) + +Support Bot on AzSK Web Site (preview): +* A new Bot has been added to our website https://azsk.azurewebsites.net to answer support queries. Please give it a try and share your feedback. + +Support for 'user comments' or 'user tags' on control results. + +* This allows users to place 'markers' on controls which are remembered in the subscription. +* This feature permits individual teams to support additional workflows for control triaging, fix tracking, etc. +* These user comments will be available as another column in the CSV produced by GSS/GRS scans by specifying "-IncludeUserComments" switch. +* Likewise, uploading user comments can be done by the command: "Update-AzSKPersistedState" and including a "UserComments" column in the CSV with the comments to include for each {resource, control} tuple. + + +Org-policy feature updates (non-CSE): +* Script to check health/correctness of org policy configuration for a given setup and to also help remediate issues that were found. +* Ability to generate compliance dashboard (PBI content pack with org CSV based on AppInsights repo) available from GitHub. + + + + +### Other improvements/bug fixes + +SVTs: +* When running GSS, if the calling user does not have enough access for certain controls, then those controls will be skipped and a warning message displayed. + +Performance improvements: +* Command startup has been sped up further. +* Telemetry calls to OMS, EventHub or WebHook - which were per-control earlier - have been batched per resource. This speeds up each control evaluation by about 2.4s. + +Controls: +* Fixed an issue with Batch service controls due to a schema change of alerts from the product team. +* Controls in resources such as ADLA that were reliant on storage encryption at rest have been made 'Informational' as SSE is enabled by default. + +CA: +* Guardrails to protect against unusual combination of parameters during CA setup in central mode or multi-CA configurations. +* Users can now explicitly request creation of new SPN for CA runtime account when calling Update-CA. (Previously we silently used an existing SPN if the user had permissions to it.) +* Get-CA now always shows a summary of CA config even if one of the interim health checks fails. It used to do so only after completion of all health checks earlier. This caused the summary to be skipped if any of the checks failed. +* Made changes to ensure that CA can function correctly even if there is a subscription level 'DoNotDelete' lock in effect. (Earlier this was causing an issue because we need to delete our schedule at the end of a CA scan.) +* Added ability to specify 'UpdateToLatestVersion' via a CA variable (earlier it could only be set inside the runbook). This lets org policy owners control their local setup to perform pre-testing of the latest AzSK module before enabling all CA deployments in the org to start using it. + + + + diff --git a/ReleaseNotes/RN180716.md b/ReleaseNotes/RN180716.md new file mode 100644 index 00000000..d4e64e7f --- /dev/null +++ b/ReleaseNotes/RN180716.md @@ -0,0 +1,66 @@ +## 180716 (AzSK v.3.4.*) + +### Feature updates + +Module Migration (AzSDK to AzSK):: +* Migration is now fully complete. The new module (AzSK) will start cleaning up older artifacts (local settings corresponding to AzSDK and the AzSDKRG resource group from subscriptions) from this release. +* All other migration related code has been removed from various cmdlets. +* Added new command to generate a compliance summary for a subscription. This lets subscription owners list the current (latest) view of all controls from a compliance standpoint. +```Powershell + Get-AzSKInfo -InfoType ComplianceInfo + ``` + +Security Verification Tests (SVTs): +* New controls for Azure Data Factory (for ADF v2 features). +* Complete controls for Bot Service and Container Instances. + +CA scan can be auto-triggered upon resource deployment: +* A new switch ‘-ScanOnDeployment’ can be used to trigger a scan for a resource group upon deployment of a new resource or update of an existing resource. (This is currently supported in normal CA mode. It is not supported in central/multi-CA account modes.) + + +Attestation workflow changes: +* Ability to mark certain controls as "not attestable" and, also, to specify permissible attestation states for others. +* Split "NotAnIssue" (which had an overloaded meaning earlier) into the following 3 states: + * (Genuine) NotAnIssue -- to represent situations where the control is implemented in another way, so the finding does not apply. + * StateConfirmed -- to represent acknowledgment by a user that the control state (e.g., IP addressed ranges on a firewall) is correct/appropriate + * NotApplicable -- the control is NA for the given design/context (e.g., a storage container that is public access ‘by design’) + + +Support for 'user comments' or 'user tags' on control results: + + This allows users to place 'markers' on controls which are remembered in the subscription. + * This feature permits individual teams to support additional workflows for control triaging, fix tracking, etc. + * These user comments will be available as another column in the CSV produced by GSS/GRS scans by specifying "-IncludeUserComments" switch. + * Likewise, uploading user comments can be done by the command: "Update-AzSKPersistedState" and including a "UserComments" column in the CSV with the comments to include for each {resource, control} tuple. + + +Org-policy feature updates (non-CSE): +* A new cmdlet (Get-AzSKOrganizationPolicyStatus) to check health/correctness of org policy configuration for a given setup and to also help remediate issues that were found. +* Provided option to download existing policies from the policy server. +* If an org is using a version of AzSK that is more than 2 releases old (current-2), then we will show a ‘deprecated’ warning to ensure that customers using org policy are staying up to date with the latest security controls. +* If a subscription is configured with a specific org policy then the scan commands run using some other (or OSS) policy will be disallowed with appropriate warnings. +* Org policy customers can now generate compliance dashboard based on a Power BI content pack and a CSV mapping subscription to org details. + +### Other improvements/bug fixes + +SVTs: +* Fixed an issue related to concurrent local file access during attestation. + +Performance improvements: +* Optimized some redundant Azure RBAC and Find-AzureRmResource calls and removed long-running provider registration checks along common code paths. +* Optimized the startup code for GSS command. + +Controls: +* The ‘Azure_Storage_Audit_AuthN_Requests’ control now supports general purpose V2 storage. +* A new control has been added that should encourage use of PIM for critical subscription level roles. We capture PIM-based RBAC details as well now. +* Fixed an issue with Logic Apps where the SVT was hanging for Logic Apps with too many connectors. + + +CA: +* Previously set OMS/AltOMS/WebHook settings can be cleared from the CA setup using a ‘-Remove’ option with Update-AzSKContinuousAssurance. +* We now handle the “missing OMS settings” condition more gracefully (to cover a case when CA is not installed for a subscription and OMS is locally not set either). + + + + + diff --git a/ReleaseNotes/RN180814.md b/ReleaseNotes/RN180814.md new file mode 100644 index 00000000..0c02f6b0 --- /dev/null +++ b/ReleaseNotes/RN180814.md @@ -0,0 +1,47 @@ +## 180814 (AzSK v.3.5.*) + +### Feature updates + +Security Verification Tests (SVTs): +* New controls for Azure Container Registry (ACR). + +ARM Template Checker: +* The ARM checker now supports multiple API versions for resource types. The versions supported are configurable at the org level. + +CICD SVT Extension: +* Support for adding multiple SVT task instances in the same pipeline. Each instance will generate logs in its own separate folder. +* SVT task will not ‘silently’ pass if, for some reason, no AzSK scan is performed. +* Control statuses other than 'Passed' or 'Error' will be now treated as 'Failed' by default. +* A new pipeline variable 'TreatAsPassed' has been introduced to allow users more control over behavior of the SVT extension in case of various control statuses other than ‘Passed’ or ‘Failed’. For e.g., using this, one may choose to have the extension treat statuses such as 'Verify','Manual','Exception' or 'Remediate' as 'Passed'. + +Org-policy feature updates (non-CSE): + +**Note:** AzSK 3.5.0 has upgraded its dependancy on AzureRM and now requires AzureRM version 6.x. It has breaking changes for RunbookCoreSetup and RunbookScanAgent present on Custom Org Policy. If you are upgrading Org Policy with AzSK version 3.5.0 using configurations(AzSK.Pre.Json), you will need to take latest runbook files with update Org policy command (*Update-AzSKOrganizationPolicy -SubscriptionId [SubId] -OrgName [OrgName] -DepartmentName [DepName] -OverrideBaseConfig CARunbooks*). If you have customized these files for your Org(like adding -UseBaselineControls inside RunbookScanAgent etc.), You will need to re-do changes after running update command. + + +* Policy owner can now use a local folder to ‘deploy’ policy to significantly improve debugging/troubleshooting experience. (Policy changes can be pre-tested locally and there’s no need to maintain a separate dev-test policy server endpoint.) +* Support for handling expiry of SAS token in the policy URL in an automated manner in local setup and CA. (Only CICD extension scenarios will need explicit updates. We will display warnings when expiry is coming up in the next 30 days.) +* Support for schema validation of org policy config JSON via the Get-AzSKOrganizationPolicyStatus command. This will reduce chances of errors due to oversight/copy-paste errors, etc. +* Teams that extend the AzSK module can now also add custom listeners to receive scan events. + +### Other improvements/bug fixes + +SVTs: +* Added helpful hints for command aliases to make users aware of the shortcut approaches to invoke their favorite AzSK commands (e.g., grs, gss, gca, etc.). Also, ensured the all command and parameter aliases are uniformly named. + +Performance improvements: +* Optimized permission checks for control attestations. Removed redundant role definition calls during all RBAC related controls. + +Controls: +* Azure_VirtualMachine_NetSec_Dont_Open_Management_Ports - Fixed an issue with port range parsing that was causing the control to be evaluated incorrectly. +* Added telemetry for identifying accounts where PIM has not been activated. +* Fixed an issue with multiple KeyVault controls (e.g., Azure_KeyVault_DP_Keys_Secrets_Check_Expiry_Date) where the ‘ListKeys’ operation performed during control validation was causing a spurious alert. +* Added telemetry to ADF controls to get visibility to commonly used linked services in the context of big data pipelines. + +Other: +* The DevOps Kit (AzSK) PowerShell module has been migrated from AzureRm 5.x to AzureRm 6.x. As always, the switch to the new dependency will be handled seamlessly in all AzSK usage modes (SDL, CICD, CA). + + + + + diff --git a/ReleaseNotes/RN180917.md b/ReleaseNotes/RN180917.md new file mode 100644 index 00000000..60a776ab --- /dev/null +++ b/ReleaseNotes/RN180917.md @@ -0,0 +1,49 @@ +## 180917 (AzSK v.3.6.*) + +### Feature updates + +Security Verification Tests (SVTs): +* Preview of security controls for Azure Databricks service. This is part of our effort to focus on Azure services that are employed in big data analytics/machine learning based on increase in enquiries about such services. + +Azure Policy-based control evaluation: +* To facilitate transition to Azure Policy, we have begun implementing control checks using Azure Policy compliance. This evaluation can be done in a side-by-side manner vis-a-vis existing implementations of the controls in AzSK. + +ARM Template Checker: +* Support nested resources within ARM templates -- especially for resources such as SQL DBs. + +'Secure Pattern' Recommendations: +* Preview of a machine learning-based feature that provides 'secure pattern' recommendations for Azure resource combinations (using data from past security scan results). + +CICD SVT Extension: +* Support for wild-cards (‘*’) in ARM Template checker file path specification. + +Org-policy feature updates (non-CSE): +* Ability to let customers control the default location where AzSK root resources will get created for subscriptions that are onboarded (for manual, CA or CICD scanning). + +### Other improvements/bug fixes + +SVTs: +* Fixed an issue related to clearing attestation state if the control starts passing outright. This ensures that if the same control fails in the future, stale attestation data does not get reused. + +Controls: +* Reviewed the behavior and JSON for all Critical, High and Medium controls across the services below to ensure that the latest Azure product changes are reflected: + * Automation, AppService, CDN, CloudService, ERvNet, SQLDatabase, KeyVault, VirtualNetwork, LogicApps, Storage, SubscriptionCore, VirtualMachine + * Controls for rest of the services will be reviewed/refreshed in the next sprint. +* Marked KeyVault controls that check secrets expiry as 'Owner-only' as data plane access is required to scan them. +* Key Vault - fixed an issue with not capturing attestation state drift in stateful controls. +* Disabled DB level controls for enabling auditing and threat detection (server-level checks are sufficient now). +* Added capability to target applicable controls for ER-connected VMs via a tag. +* Updated several controls to use the latest ASC APIs (for ASC config controls and VM controls). Controls such as disk encryption, AV, etc. will now report correctly. Also, status of Linux-related controls as available in ASC will also be visible via AzSK scans. + +CA: +* Addressed issue with CA SPN cert renewal that was blocking many teams from renewing the CA SPN certificate. This was caused by a PG transition to new OData Standards in the Azure Graph API. + +Other: +* Updated to a newer dot release of the AzureRm 6.x modules (from 6.6.0 to 6.8.1) that addresses token caching issues. This should alleviate issues some people were facing while using the DevOps kit with an SC-ALT account. +* We have added additional telemetry for ADFv2 to enhance our visibility to big data security issues/patterns. +* We explored a tool called 'Aqua' which can scan Container Registry for vulnerabilities. + + + + + diff --git a/ReleaseNotes/RN180918.md b/ReleaseNotes/RN180918.md new file mode 100644 index 00000000..cca28976 --- /dev/null +++ b/ReleaseNotes/RN180918.md @@ -0,0 +1,49 @@ +## 180917 (AzSK v.3.6.0) + +### Feature updates + +Security Verification Tests (SVTs): +* Preview of security controls for Azure Databricks service. This is part of our effort to focus on Azure services that are employed in big data analytics/machine learning based on increase in enquiries about such services. + +Azure Policy-based control evaluation: +* To facilitate transition to Azure Policy, we have begun implementing control checks using Azure Policy compliance. This evaluation can be done in a side-by-side manner vis-a-vis existing implementations of the controls in AzSK. + +ARM Template Checker: +* Support nested resources within ARM templates -- especially for resources such as SQL DBs. + +'Secure Pattern' Recommendations: +* Preview of a machine learning-based feature that provides 'secure pattern' recommendations for Azure resource combinations (using data from past security scan results). + +CICD SVT Extension: +* Support for wild-cards (‘*’) in ARM Template checker file path specification. + +Org-policy feature updates (non-CSE): +* Ability to let customers control the default location where AzSK root resources will get created for subscriptions that are onboarded (for manual, CA or CICD scanning). + +### Other improvements/bug fixes + +SVTs: +* Fixed an issue related to clearing attestation state if the control starts passing outright. This ensures that if the same control fails in the future, stale attestation data does not get reused. + +Controls: +* Reviewed the behavior and JSON for all Critical, High and Medium controls across the services below to ensure that the latest Azure product changes are reflected: + * Automation, AppService, CDN, CloudService, ERvNet, SQLDatabase, KeyVault, VirtualNetwork, LogicApps, Storage, SubscriptionCore, VirtualMachine + * Controls for rest of the services will be reviewed/refreshed in the next sprint. +* Marked KeyVault controls that check secrets expiry as 'Owner-only' as data plane access is required to scan them. +* Key Vault - fixed an issue with not capturing attestation state drift in stateful controls. +* Disabled DB level controls for enabling auditing and threat detection (server-level checks are sufficient now). +* Added capability to target applicable controls for ER-connected VMs via a tag. +* Updated several controls to use the latest ASC APIs (for ASC config controls and VM controls). Controls such as disk encryption, AV, etc. will now report correctly. Also, status of Linux-related controls as available in ASC will also be visible via AzSK scans. + +CA: +* Addressed issue with CA SPN cert renewal that was blocking many teams from renewing the CA SPN certificate. This was caused by a PG transition to new OData Standards in the Azure Graph API. + +Other: +* Updated to a newer dot release of the AzureRm 6.x modules (from 6.6.0 to 6.8.1) that addresses token caching issues. This should alleviate issues some people were facing while using the DevOps kit with an SC-ALT account. +* We have added additional telemetry for ADFv2 to enhance our visibility to big data security issues/patterns. +* We explored a tool called 'Aqua' which can scan Container Registry for vulnerabilities. + + + + + diff --git a/ReleaseNotes/RN180927.md b/ReleaseNotes/RN180927.md new file mode 100644 index 00000000..8d50a7ae --- /dev/null +++ b/ReleaseNotes/RN180927.md @@ -0,0 +1,23 @@ +## 180927 (AzSK v.3.6.1) + + +### Improvements/bug fixes + +SVTs: +* Fixed issue related to ASC API in GSS command. Any subscription not having security contacts details setup, ASC API was throwing exception and causing issue (InvalidOperation: The remote server returned an error: (404) Not Found.) + +* Fixed ARM policy validation issue + +* Fixed issue for express route connected VM. (The property 'Tags' cannot be found on this object. Verify that the property exists.) + +* Fixed invalid warning messages when user runs AzSK scans for fresh subscription + +CA: +* Fixed issue related to CA scan not happening due to long running job + + + + + + + diff --git a/ReleaseNotes/RN181015.md b/ReleaseNotes/RN181015.md new file mode 100644 index 00000000..0dbee783 --- /dev/null +++ b/ReleaseNotes/RN181015.md @@ -0,0 +1,50 @@ +## 181015 (AzSK v.3.7.0) + +### Feature updates + +Security Verification Tests (SVTs): +* Added new controls/SVTs for the following services: + * Azure AD App Proxy (requires AAD admin permissions to run) + * HDInsight (cluster level security controls) + * New controls for Service Fabric +* Added support for exclusion switches for GRS scan. Controls can be now excluded by specifying either ControlIds, ResourceTypeNames. This is to further support fine-grained control in CICD. + +### Other improvements/bug fixes + +SVTs: +* Removed separate handling of child resource controls for SQL DB, ServiceFabric, ServiceBus and EventHub. These constituted controls which were evaluated separately for ‘child’ resources (e.g., TDE control for SQL evaluated for DB v. server level). Going forward, the parent resource control will capture the evaluation outcome of child resources as well. This helps reduce complexity in handling attestation, fix-controls, compliance snapshot features etc. in such scenarios. +* The specific controls which will merge with respective parent controls are as under: + * SQLDatabase + * Azure_SQLDatabase_DP_Enable_TDE + * Azure_SQLDatabase_DP_Review_Data_Masking_Policy + * ServiceFabric + * Azure_ServiceFabric_AuthN_NSG_Enabled + * Azure_ServiceFabric_Audit_Use_Diagnostics_Log + * ServiceBus + * Azure_ServiceBus_AuthZ_Dont_Use_Policies_At_SB_Namespace + * Azure_ServiceBus_AuthZ_Use_Minimum_Access_Policies + * EventHub + * Azure_EventHub_AuthZ_Dont_Use_Policies_At_Event_Hub_Namespace + * Azure_EventHub_AuthZ_Use_Min_Permissions_Access_Policies +* Note that in the previous sprint, we had disabled those child controls for which evaluation at parent level is sufficient per PG guidance. + + +Controls: +* Included guidance for enabling diagnostics logs from the portal as well and also fixed an issue regarding steps to do so via PS cmdlet. +* Completed review of all Critical, High and Medium controls across all the DevOps Kit services to ensure that the latest Azure product changes are reflected. +* Added automation for the following Service Fabric controls: + * Azure_ServiceFabric_DP_Exposed_Endpoint_SSL_Secured, + * Azure_ServiceFabric_Availability_Replica_Stateful_Size_Set_Min_3, + * Azure_ServiceFabric_Availability_Instance_Stateless_Size_Set_Min_3 +* Removed Azure_ServiceFabric_AuthZ_Security_Mode_Enabled and Azure_ServiceFabric_DP_Enable_Encryption_Stg_Acc_Store_VHD from the scanned set of controls as Service Fabric supports these by default (with no option to disable). +* Modified/updated recommendations for the following controls: + * Azure_DataLakeAnalytics_Audit_Enable_Diagnostics_Log + * Azure_CosmosDB_AuthZ_Enable_Firewall + * Azure_CosmosDB_AuthZ_Verify_IP_Range + * Azure_NotificationHub_AuthZ_Dont_Use_Policies_At_NotificationHub_Namespace + * Azure_ServiceBus_Audit_Review_logs + * Azure_DataLakeStore_DP_Encrypt_In_Transit + + + + diff --git a/ReleaseNotes/RN181115.md b/ReleaseNotes/RN181115.md new file mode 100644 index 00000000..0448d86a --- /dev/null +++ b/ReleaseNotes/RN181115.md @@ -0,0 +1,28 @@ +## 181115 (AzSK v.3.8.0) + +### Feature updates + +Security Verification Tests (SVTs): +* Added new controls/SVTs for the following services: + * Azure Kubernetes Service (preview) + * API Management +* Ability to exclude resources via specific resource names and resource groups from (GRS) scans. (In the previous sprint, we had added support to exclude by control-id and resource type names.) +* Azure Policy-based control evaluation: + * Added ability to target a subset of subscriptions for policy-based control evaluation from the DevOps Kit. +* Org-policy feature updates (non-CSE): + * Ability to run manual and CICD scans on sovereign clouds. Please review GitHub docs for the steps needed. + * For central mode CA scanning, if central subscription is used for logging, then CA will not write to target subscription storage account any more. (Earlier, it used still use the target subscription storage account for checkpoints and other metadata.) For new setups or new target subscriptions added to the configuration, DevOps Kit will not create resources (or AzSKRG) in the target subscription. + +### Other improvements/bug fixes + +SVTs: +* HDInsight cluster level control automation (Azure_HDInsight_Deploy_Supported_Cluster_Version, Azure_HDInsight_AuthZ_Restrict_Cluster_Network_Access) +* Databricks Access control automation (Azure_Databricks_AuthZ_Enable_Workspace_Access_Control , Azure_Databricks_AuthZ_Enable_Cluster_Access_Control , Azure_Databricks_AuthZ_Enable_Job_Access_Control) + +Controls: +* Fixed bug where permission-based error message on attestation of Key Vault controls appeared only in normal attestation mode and not bulk attestation mode. Now we get it in bulk attestation mode as well. + +CICD Extension: +* Updated SVT task to work with sovereign clouds. +* Also updated ARM checker task to address removal of ‘preview’ flag. + diff --git a/ReleaseNotes/RN181217.md b/ReleaseNotes/RN181217.md new file mode 100644 index 00000000..b5be6564 --- /dev/null +++ b/ReleaseNotes/RN181217.md @@ -0,0 +1,28 @@ +## 181217 (AzSK v.3.9.0) + +### Feature updates + +Security controls for Azure DevOps (VSTS) + +* New capability (available as a separate module [AzSK.AzureDevOps]) to perform security control scanning in Azure DevOps (VSTS). This leverages the core DevOps Kit framework to seamlessly extend security scanning to VSTS and covers the following areas/scopes: Organization, Projects, Users, Connections, Pipelines (Build & Release). The overall experience is very similar to other DevOps Kit cmdlets. +Follow [page](../09-AzureDevOps(VSTS)-Security/Readme.md) for module installation and command execution guide. + +Security Verification Tests (SVTs): +* Completed security controls for the following: + * Azure Kubernetes Service (AKS) + * API Management (APIM) +* Ability to scan Databricks using an 'in-cluster' scan agent (Python notebook). Please see below for the steps on how to set this up. We are exploring this as a general approach to expand AzSK scans into the 'data' plane for various cluster technologies. +* Ability to customize naming of severity levels of controls (e.g., instead of High/Medium, etc. one can now have Important/Moderate, etc.) with the changes reflecting in all avenues (manual scan results/CSV, OMS, compliance summaries, dashboards, etc.) +* Org-policy feature updates (non-CSE): + * The ARM Checker task in AzSK CICD Extension now respects org policy ' this will let org policy owners customize behavior of the task. (Note that this was possible for the SVT task earlier'only the ARM Checker task was missing the capability.) + * Ability to run CA in sovereign clouds + ability to apply custom org policy for SDL, CICD and CA for such subscriptions. (Please review [GitHub docs](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-support-for-azure-government-and-azure-china-1) for the steps needed.) + +### Other improvements/bug fixes + +Controls: +* Fixed a bug in the PIM-related ('Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access') control to check for (null) condition where there are no members in permanent role. +* The DevOps Kit config health control ('Azure_AzSKCfg_Check_Health_of_CA') was unnecessarily enforcing Security Reader permission. It should now work just with 'Reader' permission. +* Updated recommendations, rationale, etc. for multiple controls in preparation for the CSE compliance drive. + +CICD Extension: +* Fixed an issue in ARM Template Checker where exclude files parameter was not honored recursively in a folder hierarchy. diff --git a/ReleaseNotes/RN190116.md b/ReleaseNotes/RN190116.md new file mode 100644 index 00000000..fc0786a4 --- /dev/null +++ b/ReleaseNotes/RN190116.md @@ -0,0 +1,66 @@ +## 190116 (AzSK v.3.10.0) + +### Feature updates + +Security Verification Tests (SVTs): +* Added support for scanning preview baseline controls for commands GRS/GSS/GACS/GAI using flag -UsePreviewBaselineControls (upbc) + * This flag can be used solo or together with the -UseBaselineControls for each of these commands. + +* Added control in subscription scan to validate mandatory tags at scopes as specified in org policy. Tags shall be validated for name and allowed set of values (or type). + * To try this, use: gss -s 'subscriptionId' -ControlIds 'Azure_Subscription_Config_Add_Required_Tags' + +OMS product team migration/rebranding to ‘Log Analytics’: + * Validated that all DevOps Kit OMS scenarios continue to work post transition to 'Log Analytics'. + + +(Preview) AzSK module for Azure DevOps (VSTS) + * Added automation for more controls for Azure DevOps (VSTS) + * AzureDevOps_Organization_SI_Review_InActive_Users + * AzureDevOps_User_AuthN_Disable_Alternate_Cred + * AzureDevOps_Build_SI_Review_InActive_Build + * AzureDevOps_Build_SI_Review_InActive_Release + + To try the new Azure DevOps scanning functionality, use the following: + + VSTS scanning is packaged in a separate module called AzSK.AzureDevOps! + + `` + Install-Module AzSK.AzureDevOps -Scope CurrentUser + `` + + `` + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "AzSKtestvso"` + -ProjectNames "AzSKDemoRepo"` + -BuildNames "AzSKDemo_CI"` + -ReleaseNames "AzSKDemo_CD" + `` + +* Org-policy feature updates (non-CSE): + * ARM Template Checker: + * Fixed an issue where the 'isEnabled' property was not being respected at individual control level. + * Org policy schema has been updated to include recently added properties to various AzSK objects. + * No action needed from org policy owners. + * If needed, the Get-AzSKOrganizationPolicyStatus command can be used to validate that properties used in your policy are schema compliant + * Changed ‘org -> subscription’ mapping approach following deprecation of older approach by Application Insights product team. If you need to upload/refresh your org -> subscription details, please use the new approach from the "Create Cloud Security Compliance Report…" section in AzSK organization policy docs at https://aka.ms/devopskit/docs. + + +### Other improvements/bug fixes + +* SVTs: + * N/A +* Controls: + * Recommendation updated for firewall/IP-based controls to support the scenario of indeterminate IP range. + * For Logic Apps SVT, if an API Connection object is shared by two different Logic Apps then, it will be scanned only once. + * APIM controls - changed code to filter 'product/API' controls if these artefacts do not exist in the service instance. + * Fixed an issue with AzSKCfg controls - if a user does not have permission then the result will be 'Manual' (as opposed to 'Failed'). + * Anon access check for Azure Storage Blobs control will not trigger for ADLS-v2 objects. + +* CICD Extension: + * N/A + +* CA: + * N/A + +* Log Analytics (OMS) + * Added 'ScannedBy' field in the scan events sent to Log Analytics. + diff --git a/ReleaseNotes/RN190215.md b/ReleaseNotes/RN190215.md new file mode 100644 index 00000000..a6214eda --- /dev/null +++ b/ReleaseNotes/RN190215.md @@ -0,0 +1,4 @@ +## No 1902 sprint release: + +In the 1902 sprint, we have started work to migrate from AzureRm to Az-* module. This has taken longer than expected due to a couple of issues with Az-* cmdlets. +We are going to continue our effort to resolve the issues and work on stabilizing the module in 1903 and hope to do a combined release for 1902 and 1903 mid-March. diff --git a/ReleaseNotes/RN190315.md b/ReleaseNotes/RN190315.md new file mode 100644 index 00000000..b767ccdd --- /dev/null +++ b/ReleaseNotes/RN190315.md @@ -0,0 +1,81 @@ +## 190315 (AzSK v.3.11.0) + +### Feature updates + +Migration from AzureRM to Az-*: +* This release of AzSK has switched to using the new Az-* PowerShell libraries instead of AzureRM for Azure PS support. By and large, this should be a seamless transition for DevOps Kit users except for the caveats below: + * When using AzSK from PS console (SDL mode of AzSK), exercise care to not accidentally import (pre-existing) AzureRM libraries into the session. As always, after upgrade, it is best to start with “import-module AzSK” in a new PS session. + * Remember that for Az-* modules, you should use ‘Connect-AzAccount’ and ‘Disconnect-AzAccount’ (as opposed to ‘Connect/Disconnect-AzureRMAccount’). + +* We have also updated control recommendation, fix-scripts etc. to reflect the change from AzureRM to Az-*. + +* We shall be updating the public (Git) AzSK docs over the next few days (to change references to AzureRm cmdlets to corresponding Az-* ones). If you update your local setup of DevOps Kit, remember to use the ‘Az-*’ version of all cmdlets instead of the ‘AzureRm’ versions. In most cases, this simply amounts to replacing ‘AzureRm’ with ‘Az’ in a cmdlet (e.g., Get-AzureRmContext to Get-AzContext). + +* If you have set up your own org policy, make sure to go through the 'Org-policy feature updates' section below. + +Security Verification Tests (SVTs): + +* Added control to check that a vulnerability management solution is configured for VMs (both Windows and Linux). The control checks for the extension (e.g., Qualys) is enabled and in a ‘healthy’ provisioning state. The vuln solution required and expected minimum version are configurable for an organization. + +* Added control to require that “Standard” tier is enabled for Azure Security Center for a subscription. (The “Standard” tier for ASC provides a lot of security capabilities which the “Free” tier does not.) + + +* (Preview) New cmdlet for PIM management: + * Integrated a script into AzSK that should help with Privileged Identity Management (PIM) configuration. + * To try this run: + ```Powershell + Set-AzSKPIMConfiguration + ``` + +* (Preview) In-cluster security scans for Databricks, Kubernetes, HDInsight Spark + * We have implemented support for in-cluster security control scans for Databricks, Kubernetes and HDInsight Spark clusters using an approach similar to AzSK Continuous Assurance (CA). + + * Currently, a total of 13 controls are available for Databricks, 7 for Kubernetes and 11 for HDInsight Spark. + + * This feature is currently available via a separate setup command. We will publish the instructions at https://aka.ms/devopskit/inclusterca in next few days. + +* Added support for additional service types to DevOps Kit ARM Checker: + * Key Vault, Service Fabric, Virtual Network, Logic Apps and Container Registry + +* OMS migration to Log Analytics: + * The cmdlets Install-AzSKOMSSolution and Set-AzSKOMSSettings will be deprecated soon. Please use Install-AzSKMonitoringSolution and Set-AzSKMonitoringSettings in lieu of these. + +* Alerts for additional resource types: + * Enhanced Set-AzSKAlerts (which gets called also from Set-AzSKSubscriptionSecurity) to include alerts for security-relevant activities on several new resource types (e.g., APIM, HDInsight, Load Balancer, etc.) + + + +* Org-policy feature updates: + * Fixed an issue which was causing an unexpected error in org policy download via + ``` + Get-AzSKOrganizationPolicyStatus -DownloadPolicy + ``` +* We have validated steps required to add an entirely new (hitherto unsupported) service SVT to AzSK using the extensibility model. +* Org policy users will need to perform explicit steps to migrate from AzureRM to Az-* based AzSK module which will be published at the link below. +* Note: Important changes/updates required for Org Policy users are published 1 working day after each release at: https://aka.ms/devopskit/orgpolicy/updates + + +### Other improvements/bug fixes + +* SVTs: + * Fixed an issue related to a product change in default settings for Azure Security Center policies (this was resulting in a 'endpointProtectionMonitoringEffect property not found’ error for subscriptions where ASC policies had never previously been set). + * Changed Databricks SVT to skip the following controls which were failing due to the external lock that exists on Databricks resource groups: + * Azure_Storage_AuthN_Dont_Allow_Anonymous, + + * Azure_Storage_Audit_AuthN_Requests, + + * Azure_Storage_DP_Restrict_CORS_Access + +* ARM Template Checker: + * Fixed an issue where for certain templates the ARM checker cmdlet was going into an infinite loop. + +* Controls: + * Fixed an issue related to log retention period check for enable diagnostics log control for all resources. + + * The storage container/blob public access check control (Azure_Storage_AuthN_Dont_Allow_Anonymous) will no longer require ‘Owner’ access. This makes it possible to check the control from CA which is a big improvement to ‘continuous’ visibility for storage container/blob access control config. + + * Fixed a bug related to discrepancy in control status on configuring Custom Domains and SSL on Azure App Service (Azure_AppService_DP_Use_CNAME_With_SSL) + + * Fixed an issue in implementation of Cloud Service anti-malware control (Azure_CloudService_SI_Enable_AntiMalware) + + diff --git a/ReleaseNotes/RN190415.md b/ReleaseNotes/RN190415.md new file mode 100644 index 00000000..ac9aeb5f --- /dev/null +++ b/ReleaseNotes/RN190415.md @@ -0,0 +1,87 @@ +## 190415 (AzSK v.3.12.0) + +### Feature updates + + +* ARM Template Checker: + * The ARM Template Checker now supports templates that use parameters files. The ARM Checker CICD task can also leverage this capability. So long as the parameter file name corresponds to the ARM template file name (e.g., Foo.parameters.JSON for Foo.JSON), multiple templates with corresponding parameter files can be scanned by specifying the containing folder. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * A new module called ‘AzSK.AAD’ can be used to check for security configuration and best practices for various artifacts in an AAD tenant. + * Two separate commands are provided – one targeted for AAD-admin (scan all objects) and another for the end user (scan ‘user-owned’ objects). + * To try this, use the following steps: + + AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + ```Powershell + Install-module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # to check the tenant (admin) + Get-AzSKAADSecurityStatusUser # to check objects you own (user) + ``` + + Some caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the ‘-MaxObj’ switch in the cmdlets. + +* Security Verification Tests (SVTs): + * The tag compliance control has been updated to make tag comparison behavior ‘case-insensitive’ (i.e., ComponentID, componentID, ComponentId, etc. will be treated as the same tag). + * To review your tagging compliance use: + ```Powershell + gss -s 'subscriptionId' -ControlIds 'Azure_Subscription_Config_Add_Required_Tags' + ``` + +* (Preview) In-cluster security scans for ADB, AKS, HDI Spark + * HDI and ADB CA now support sending events to App Insights + * ADB CA support scanning multiple clusters now + * New controls have been added to AKS scan + * Several UX and perf improvements in setup and scan job. + * To try in-cluster CA see instructions at https://aka.ms/devopskit/inclusterca + +* Log Analytics - additional filters: + * More filters have been added to the Log Analytics view (support filtering by ResourceType, ControlSeverity and Subscriptions). To get these you will need to recreate the view using the “Install-AzSKMonitoringSolution” cmdlet. + +* Migration to Az- modules: + * We have switched back to the product implementation of ‘Set-AzStorageBlobContent’ and ‘Get-AzStorageBlobContent’ at various places in AzSK (runbooks, module code, etc.). In 3.11.0, we had used a workaround for these to make CA work in spite of this issue in Azure Automation. + * A couple of reminders: + * When using AzSK from PS console (SDL mode of AzSK), exercise care to not accidentally import (pre-existing) AzureRM libraries into the session. + * Remember that for Az-* modules, you should use ‘Connect-AzAccount’ and ‘Disconnect-AzAccount’ (do not use ‘Login-AzureRmAccount’ or ‘Connect/Disconnect-AzureRMAccount’). + + +* (Preview) AzSK module for Azure DevOps (VSTS) + * Several new controls have been added to the AzSK.AzureDevOps module. These should encourage better RBAC, branch and deployment hygiene and limit exposure from inherited permissions of global groups. + #VSTS scanning is packaged in a separate module called AzSK.AzureDevOps! + ```Powershell + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +• Org-policy updates (non-CSE): +o No org-policy specific updates in this release. + + +### Other improvements/bug fixes + +* Other improvements/bug fixes + * SVTs: + * N/A + +* Controls: + * The authentication control for AppServices, Azure_AppService_AuthN_Use_AAD_for_Client_AuthN, will now check UnauthenticatedClientAction and fail if the latter is set to ‘Allowed’. + * The Azure_AppService_DP_Dont_Allow_HTTP_Access_Fn & Azure_AppService_AuthN_Use_AAD_for_Client_AuthN controls will now be scanned even if the AppService is in 'stopped’ state + * The ‘PIM-check’ control (Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access) has been augmented to support a whitelist. Using this, the “Subscription Admins” group which gets inherited as ‘Owner’ from root (out-of-box PG behavior) will not result in a control failure. + * Changed encrypted variables control to skip more AzSK-created variables in AzSKRG. + * The VM disk encryption check has been updated to report (ASC-based status) correctly even for deallocated VMs. + +* ARM Checker: + * Fixed a regex issue for the ‘-ExcludeFiles’ switch. Earlier it was excluding more files than what the user intended. +* CA: + * Changed CA implementation so that the first scan after a fresh CA installation happens right away (instead of the next day after install). + +* Log Analytics (OMS) + * N/A + + diff --git a/ReleaseNotes/RN190515.md b/ReleaseNotes/RN190515.md new file mode 100644 index 00000000..e17cad82 --- /dev/null +++ b/ReleaseNotes/RN190515.md @@ -0,0 +1,119 @@ +## 190515 (AzSK v.3.13.0) + +### Feature updates + + +* Privileged Identity Management (PIM) helper cmdlets: + * New capabilities in cmdlets to make Privileged Identity Management (PIM) operations quicker via automation. + * Set-AzSKPIMConfiguration for configuring/changing PIM settings: + * Assigning users to roles (-AssignRole) + * Activating your roles (-ActivateMyRole) + * Deactivating your roles (-DeacctivateMyRole) + * Converting permanent assignments at subscription/RG scope to PIM (-ConvertPermanentAssignmentsToPIM) + * Removing permanent assignments altogether (-RemovePermanentAssignments) + + * Get-AzSKPIMConfiguration for querying various PIM settings/status: + * List your PIM-eligible roles (-ListMyEligibleRoles) + * List permanent assignments (-ListPermanentAssignments) + * List PIM assignments (-ListPIMAssignments) + + * Detailed documentation for all new flags along with sample cmdlets will be available ~a day after release in the ‘01-Subscription-Security’ section of our docs at https://aka.ms/devopskit. + +* Adoption of Azure Security Center (ASC) policies: + * The Set/Update-AzSKSubscriptionSecurity and Set-AzSKAzureSecurityCenterPolicies cmdlets have been expanded to set 25+ new policies from the ‘ASC default initiative’ as ‘required’. The corresponding ASC policy check control has also been modified to check that these policies have been setup correctly. + * About 30+ other policies are currently available as ‘optional’. These can be setup by using the ‘-OptionalPolicies’ flag in Set-AzSKAzureSecurityCenterPolicies and aren’t checked in the ASC policy check control. + + +* (Preview) Security Scan for Azure Active Directory (AAD) + * The new AzSK.AAD module has been enhanced to send telemetry events to a Log Analytics workspace. You can use the AzSK.AAD version of Set-AzSKLogAnalyticsSettings to enable this. + * Control scan events can also be sent to a custom App Insights instance. You can use Set-AzSKLocalAIOrgTelemetrySettings to enable this. + * A new ‘None’ value for the switch -ObjectType can help you focus just on tenant config controls and skip checking individual object instances (users, groups, apps, etc.) altogether. + * In case you have not tried the basic cmdlets yet, use following steps:: + + AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + ```Powershell + Install-module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # to check the tenant (admin) + Get-AzSKAADSecurityStatusUser # to check objects you own (user) + ``` + + Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the ‘-MaxObj’ switch in the cmdlets. + +* ARM Template Checker: + * The ARM Template Checker now supports 3 new service types (Container Instances, EventHub, Search). + +* Security Verification Tests (SVTs): + * N/A + +* (Preview) In-cluster security scans for ADB, AKS, HDI Spark + * Schema used for AI telemetry standardized across ADB, AKS and HDI scans. + * To try out in-cluster CA, see instructions at https://aka.ms/devopskit/inclusterca + We are looking for early adopters and will be happy to handhold you through the setup. + + +* Log Analytics - additional filters: + * The ‘ComponentId’ and ‘Env’ tags for subscription and resource groups are now sent to Log Analytics as part of DevOps Kit scan events. + * This can help further refine/group the queries and views when using the DevOps Kit log analytics/monitoring solution. + + +* Migration to Az- modules: + * No new updates. + * Caveats: + * When using AzSK from PS console (SDL mode of AzSK), exercise care to not accidentally import (pre-existing) AzureRM libraries into the session. + * Remember that for Az-* modules, you should use ‘Connect-AzAccount’ and ‘Disconnect-AzAccount’ (do not use ‘Login-AzureRmAccount’ or ‘Connect/Disconnect-AzureRMAccount’). + + + +* (Preview) AzSK module for Azure DevOps (VSTS) + * No new updates. You can try the scan cmdlet using: + + * VSTS scanning is packaged in a separate module called AzSK.AzureDevOps! + + ```Powershell + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +• Org-policy updates (non-CSE): + * Support for extensibility for ARM Checker. You can now add new controls to existing services and also add altogether new services to be scanned in the ARM Checker for your organization. + * Some of the re-configuration of DevOps Kit alerts by mandatory v. optional will become available in the next sprint. + + + +### Other improvements/bug fixes + +* Other improvements/bug fixes + * Subscription Security: + * Modified Update-AzSKSubscriptionSecurity/Set-AzSKARMPolicies so that the cmdlets will now remove deprecated (previously setup but not mandatory anymore) AzSK ARM policies from subscriptions. + + * SVTs: + * N/A + +* Controls: + * The authentication control for AppService, Azure_AppService_AuthN_Use_AAD_for_Client_AuthN, will now validate that the app is not using a non-tenant/non-AAD authentication provider (Facebook, Twitter, etc.). + + * New control called Azure_KeyVault_Avoid_Excessive_Versions_Keys_Secrets added for key vault to check excessive number of past keys and secret versions (>3 enabled versions). + + * The control for checking tagging compliance can now support ‘whitelisting’ using RegEx. This allows org-wide exemption of certain resource groups from enforcement of the control. + + * New control called Azure_VirtualMachine_SI_Deploy_GuestConfig_Extension added to check guest-configuration extension for Windows & Linux VMs. The control checks that the extension is provisioned successfully, the VM has a ‘system-assigned’ managed identity and an org-configurable assignment name. + + * Perf-enhancements for the following Key Vault controls: Azure_KeyVault_DP_Keys_Protect_By_HSM, Azure_KeyVault_DP_Keys_Secrets_Check_Expiry_Date and Azure_KeyVault_AuthN_Key_Min_Operation + + +* ARM Checker: + * Controls that emit a ‘Verify’ result can be skipped now using the ‘-SkipControlsFromFile’ feature. +* CA: + * Added a throttling mechanism to help CA runbooks run to completion when scanning large subscriptions containing APIM objects. These were being terminated earlier by Azure due to ‘excessive socket accumulation’. (The sockets would get released over time but not fast enough.) The throttling mechanism avoids the build-up. + +* Log Analytics (OMS) + * N/A + + diff --git a/ReleaseNotes/RN190614.md b/ReleaseNotes/RN190614.md new file mode 100644 index 00000000..f03dfbcf --- /dev/null +++ b/ReleaseNotes/RN190614.md @@ -0,0 +1,120 @@ +## 190614 (AzSK v.3.14.0) + +### Feature updates + + +* DevOps Kit for PowerShell Core (Preview): + * We have a preview drop of the DevOps Kit module ready on PowerShell core. This covers all DevOps Kit cmdlets except for Continuous Assurance (CA). + * The CA related cmdlets (ICA, GCA, RCA, etc.) will be completed in the next sprint. + * We will publish the steps to try this out at https://aka.ms/devopskit/pscore by Monday. + +* ARM Template Checker: + * Support for targeting specific control-ids for both scanning and exclusion. + * Support for org baseline (and preview baseline) switches. + + +* Security Verification Tests (SVTs): + * Support for guest configuration policy extension and control evaluation for Windows and Linux VMs. This provides visibility to ‘in-guest’ security policy compliance for VMs. This is covered through two controls: + * Azure_VirtualMachine_SI_GuestConfig_Policy_Health + * Azure_VirtualMachine_SI_Deploy_GuestConfig_Extension + + +* CICD: + * Impt: After this release, the AzSK CICD extensions will not work on Visual Studio 2015 hosted agents. This is because the Az-* PowerShell libraries are not available in these agents. Please migrate to VS-2017 or VS-2019 based hosted agents. + * The ARM Checker CICD Extension now has the following capabilities: + * Support for 'ExtendedCommand' to allow users to customize the ARM scan in CICD. + * Support for 'TreatAsPassed' for controls that get evaluated as 'Verify'. + +* (Preview) In-cluster security scans for ADB, AKS, HDI Spark + * Added support for Update-CA functionality for Databricks and HDI Spark. + * Added new controls for Databricks to cover init scripts and installed libraries. + +* Log Analytics: + * Changed names for OMSWorkspaceId and OMSSharedKey to LAWSId and LAWSSharedKey respectively (similar changes for AltOMS-* variables). + * For CSEO CA, these changes will be addressed automatically (no user intervention needed). + * For OSS and Org Policy customers, these changes to the names need to be pushed by subscription owners via Update-CA. + * For CICD tasks that send events to OMS/Log Analytics, users will have to change/add the new variables in the pipeline variables (instead of the old/existing ones). + +* The following new controls have been added to the Azure DevOps (VSTS) security scan module. These reflect some RBAC practices and findings from security testing performed by DSRE on the CSEO tenant: + * AzureDevOps_Organization_SI_Review_Shared_Extensions + * AzureDevOps_AgentPool_Build_AuthZ_Grant_Min_RBAC_Access + * AzureDevOps_AgentPool_AuthZ_Disable_InheritPermissions + * AzureDevOps_AgentPool_SI_Lockdown_Machine + * AzureDevOps_AgentPool_SI_Missing_OS_Patches + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * Set-AzSKPIMConfiguration for configuring/changing PIM settings + * Get-AzSKPIMConfiguration for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + pim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + ```Powershell + Install-module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # to check the tenant (admin) + Get-AzSKAADSecurityStatusUser # to check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the ‘-MaxObj’ switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (VSTS) + * You can try the scan cmdlet using: + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" +. +* Org-policy updates (for non-CSEO users): + * Support for segregating DevOps Kit alerts by mandatory v. optional is now available for all customers. The default cmdlets (Set-AzSKSubscriptionSecurity and Set-AzSKAlerts) will only setup ‘mandatory’ subset of activity alerts. (Please see previous sprint release notes for more.) + * Please review the variable name changes for OMS workspace and shared key above. + + +### Other improvements/bug fixes + +* Subscription Security: + * N/A + +* SVTs: + * GRS/GSS/GACS command outputs CSV now includes the ‘IsPreviewBaselineControl’ as a separate column (not bundled with 'baseline' control column anymore). + * Fixed an issue whereby while using '-ubc' and '-upbc' switches together, some resources were getting scanned twice. + + +* Controls: + * The behavior for Azure Security Center (ASC) alerts control has been modified to target high risk alerts only. + * ASC alerts that are of severity 'high' will results in control failure if/when they are > 30 days old. + * The Azure_VirtualMachine_NetSec_Justify_PublicIPs control will not be scanned for VMs spun up in Databricks-managed resource groups. + * In preparation for migration to new Azure platform alerts, alerts-related controls for various services (APIM, Stream Analytics, Batch, etc.) have been migrated to check for new alerts (control fix recommendations have been changed accordingly). Classic alerts will be retired by Azure in Aug-2019. + * Added a check to skip Azure_Storage_AuthN_Dont_Allow_Anonymous control for storage of type 'File Share (Preview)'. + + +* Security IntelliSense is now supported on VS 2019. You can install it using the instructions [here](https://github.com/azsk/DevOpsKit-docs/blob/master/02-Secure-Development/Readme.md). + + +* ARM Template Checker: + * Fixed a bug that was causing file names with spaces in them to get skipped during parsing. + * Fixed a bug that was causing some SQL controls to get scanned for a CosmosDb ARM template. + +* CA: + * N/A + +* Log Analytics (OMS) + * N/A + +* Other + * Updated Get-AzSKInfo cmdlet to: + * include version info for ASC + * support '-IsPreviewBaselineControl' flag (in 'gai -infotype complianceInfo') + + + diff --git a/ReleaseNotes/RN190715.md b/ReleaseNotes/RN190715.md new file mode 100644 index 00000000..76d99fe1 --- /dev/null +++ b/ReleaseNotes/RN190715.md @@ -0,0 +1,122 @@ +## 190715 (AzSK v.3.15.0) + +### Feature updates + + +* DevOps Kit for PowerShell Core (Preview): + * All the salient features of DevOps Kit (CA, SVT, Org-policy and other AzSK PowerShell cmdlets) are now supported on PowerShell Core. + * The CA related cmdlets (ICA, GCA, RCA, etc.) will be completed in the next sprint. + * The instructions to try these out will be updated at https://aka.ms/devopskit/pscore . + +* (Preview) Credential Hygiene: + * We now offer a register-and-track solution to help monitor the last update of your credentials. This will help you periodically track the health of your credentials which are nearing expiry/need rotation. + * The following cmdlets have been introduced to support this functionality: + * **New-AzSKTrackedCredential** to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * **Get-AzSKTrackedCredential** to list the onboarded credential(s). + * **Update-AzSKTrackedCredential** to update the credential settings and reset the last updated timestamp. + * **Remove-AzSKTrackedCredential** to deboard a credential from AzSK tracking. + * A new control ‘Azure_Subscription_Check_Credential_Rotation’ has been introduced in the GSS scan to help keep a check on all the tracked credentials. + +* DevOps Kit controls expressed as Azure Policy (in progress): + * Authored Azure Policy for 5 more DevOps Kit baseline controls. These have been submitted to the Azure Security Center (ASC) team for inclusion in the ASC initiative. + + +* Security Verification Tests (SVTs): + * Support for severity-based filter for GRS & GSS cmdlets. + +* ARM Template Checker: + * Support for severity-based filter for ARM template scans. + +* CICD: + * N/A + +* (Preview) In-cluster security scans for ADB, AKS, HDI Spark + * In tune with the regular DevOps Kit CA cmdlets (ICA, GCA, UCA & RCA), in-cluster CA now supports the following (besides the install-cmd): + * Get-AzSKContinuousAssuranceForCluster + * Update-AzSKContinuousAssuranceForCluster + * Remove-AzSKContinuousAssuranceForCluster + * The above cmdlets are currently available in the main AzSK module for Databricks and HDI Spark. For AKS, use instructions available at https://aka.ms/devopskit/inclusterca + + +* Log Analytics: + * N/A + + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * Set-AzSKPIMConfiguration for configuring/changing PIM settings + * Get-AzSKPIMConfiguration for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + pim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + ```Powershell + Install-module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # to check the tenant (admin) + Get-AzSKAADSecurityStatusUser # to check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the ‘-MaxObj’ switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (VSTS) + * You can try the scan cmdlet using: + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" +. +* Org-policy updates (for non-CSEO users): + * See CA section in “Other improvements/bug fixes” below to install CA in environments where subscription ownership resides with a different team. + + +### Other improvements/bug fixes + +* Subscription Security: + * N/A + +* SVTs: + * N/A + + +* Controls: + * The behavior for Azure Security Center (ASC) setup control has been enhanced to evaluate ASC policy state (enabled/disabled) across multiple initiatives. + * VM controls scan performance has been improved to fetch resource-specific ASC recommendations only. + * Added new control ‘Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG’ to check persistent access at resource group level. This control will get evaluated only during CA scan. + * Added the following new controls for app service: + * Azure_AppService_DP_Use_Approved_TLS_Version + * Azure_AppService_DP_Verify_Installed_Extensions + * Azure_AppService_AuthZ_Configure_IP_Restrictions + * Azure_AppService_DP_Review_CORS_Request_Credential + + +* ARM Template Checker: + * Following new controls have been added to ARM Checker: + * Azure_APIManagement_NetSec_Configure_Virtual_Network_For_APIM + * Azure_APIManagement_AuthN_Use_Managed_Service_Identity + * Azure_APIManagement_DP_Use_HTTPS_URL_Scheme + * Azure_HDInsight_Deploy_Supported_Cluster_Version + +* CA: + * Install-AzSKContinuousAssurance (ICA) can now be run even without owner permissions at subscription scope. The user who ran ICA must get the actual owners to configure RBAC for the AzSK_SPN on the subscription. + * Reduced size of metadata downloads for some VM controls should lead to lower incidence of CA runbook suspension in large subscriptions. + * Fixed a bug in CA whereby for external users, CA scans were ignoring resource groups (as specified in the resource groups parameter of ICA) and scanning everything in the subscription. + + +* Log Analytics (OMS) + * N/A + +* Other + * N/A + + + diff --git a/ReleaseNotes/RN190814.md b/ReleaseNotes/RN190814.md new file mode 100644 index 00000000..4ec0b151 --- /dev/null +++ b/ReleaseNotes/RN190814.md @@ -0,0 +1,129 @@ +## 190814 (AzSK v.4.0.0) + +### Feature updates + + +* (Preview) Restructuring of DevOps Kit framework for reusability: + * From the learnings of developing DevOps Kit-based AAD & ADO scanners, we have done an extensive refactoring exercise to make it easy to leverage core framework capabilities to create security/compliance scanners for other technology areas. + +* Privileged Identity Management (PIM): + * The following new switches have been added to PIM cmdlets: + * -ListSoonToExpireAssignments switch in Get-AzSKPIMConfiguration cmdlet to list eligible assignments that will expire within specified duration. + * -ExtendExpiringAssignments switch in Set-AzSKPIMConfiguration cmdlet to extend the eligibility of assignments by a specified duration. + +* (Preview) Credential Hygiene: + * Credential hygiene events generated via control scan will now be send to DevOps Kit configured log analytics workspace. + * We have also introduced New-AzSKTrackedCredentialGroup cmdlet to configure email alerts to notify users about AzSK-tracked credentials that are about to expire or have already expired. + +* (Preview) Approved exception support in control attestation: + * The control attestation feature has been augmented to support a special “GRC-approved” exception for controls. This covers scenarios where controls cannot be passed due to limitations/conditions beyond the realm of application teams (e.g., a product bug). It can be triggered by using the new -AddException switch during attestation. + + + +* Security Verification Tests (SVTs): + * Support for severity-based filter for Get-AzSKControlsStatus (GACS) command. + +* ARM Template Checker: + * N/A + +* CICD: + * Support for a switch to toggle whether to ‘pass’ or ‘fail’ the pipeline if no controls are scanned via SVT and ARM Checker task (default is ‘fail’). + * This flag is useful in situations where due to scan criteria (e.g., -Severity ‘Critical’) no controls might be scanned when the task runs. + + +* (Preview) In-cluster security scans for ADB, AKS, HDI Spark + * In-cluster CA now supports sending scan telemetry to log analytics (LA) workspace. This can be configured by using the Install-AzSKContinuousAssuranceForCluster cmdlet. (If no LA workspace is specified, the workspace configured for the regular DevOps Kit CA in the subscription will be used.) + * The DevOps Kit monitoring solution (Install-AzSKMonitoringSolution) views will now show in-cluster compliance status for your HDInsight and Databricks workspaces. + + +* Log Analytics: + * N/A + +* Org-policy updates (for non-CSEO users): + * Fixed an issue in Get-AzSKOrganizationPolicyStatus cmdlet where in local debugging mode, extension files weren't getting loaded. + * Fixed an issue in Get-AzSKOrganizationPolicyStatus cmdlet checks which were failing after fresh installation of org-policy. + * Improved messages in the org-policy cmdlets (Install, Get & Update- org policy). + * Introduced DisableOrgPolicyCheckForSession flag in Set-AzSKPolicySettings cmdlet to disable enforcement of org-policy for the current PS session. This helps in situations when an org-policy owner is working with multiple side-by-side policies. + + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * Set-AzSKPIMConfiguration for configuring/changing PIM settings + * Get-AzSKPIMConfiguration for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + pim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + ```Powershell + Install-module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # to check the tenant (admin) + Get-AzSKAADSecurityStatusUser # to check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the ‘-MaxObj’ switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (VSTS) + * You can try the scan cmdlet using: + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" +. +* Org-policy updates (for non-CSEO users): + * See CA section in “Other improvements/bug fixes” below to install CA in environments where subscription ownership resides with a different team. + + +### Other improvements/bug fixes + +* Subscription Security: + * N/A + +* SVTs: + * N/A + + +* Controls: + * The behavior for the controls ‘Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG, Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access’ has been enhanced to check persistent access of users and groups on resource group and subscription scope respectively. + * VM control ‘Azure_VirtualMachine_SI_Enable_Antimalware’ has been improved by adding Sophos antivirus check for Linux VMs. + * Added a new control ‘Azure_VirtualMachine_SI_Deploy_Required_Extension’ which can be used by organizations to specify which VM extensions are mandatory across the org. Different sets of extensions can be specified for Windows and Linux VMs. + + + +* ARM Template Checker: + * N/A + +* CA: + * N/A + +* Privileged Identity Management (PIM) + * Fixed an issue where Set-AzSKPIMConfiguration cmdlet was not working due to a recent change in the PIM API. + * Set-AzSKPIMConfiguration cmdlet alias has been renamed to setpim (previously aliased as pim). + +* Azure DevOps (VSTS) + * Fixed a bug where a control scan was throwing an exception if no pool agents were found in the project. + + +* Log Analytics (OMS) + * N/A + +* Other + * GenerateFixScript flag now works for subscription ARM policy compliance control. + * Updated the fix-script for the control 'Azure_AppService_BCDR_Use_Multiple_Instances'. + * Fixed an issue in Get-AzSKInfo -InfoType SubscriptionInfo whereby incorrect CA runbook version was being reported. + * Fixed an issue to respect the -UsePreviewBaselineControls switch in Get-AzSKInfo -InfoType ControlInfo. + +* AzSK has been upgraded to use the latest Azure PowerShell libraries (Az v.2.4.0). + + + + diff --git a/ReleaseNotes/RN190916.md b/ReleaseNotes/RN190916.md new file mode 100644 index 00000000..a276cb7e --- /dev/null +++ b/ReleaseNotes/RN190916.md @@ -0,0 +1,113 @@ +## 190916 (AzSK v.4.1.0) + +### Feature updates + +* Security Verification Tests (SVTs): + * New SVTs for two Azure services - Azure Database for MySQL and PostgreSQL. + * Automated controls include checks for firewall & virtual network rules, SSL connection, backup & disaster recovery, advanced threat protection and diagnostic settings as applicable. + + +* (Preview) Security IntelliSense (SecIntel) extension for Visual Studio Code: + * SecIntel for Visual Studio Code can downloaded from [here](https://marketplace.visualstudio.com/items?itemName=azsdktm.SecurityIntelliSense). + * This is a VS Code editor extension mainly targeted towards providing quick and inline security suggestions and fixes for Azure related C# source code, web projects and crypto-related code. +* Privileged Identity Management (PIM): + * We have added capabilities for admin to configure role settings like maximum activation duration, maximum allowed days for assignment and MFA requirement on activation for a specific role on a resource using the below command + + setpim -ConfigureRoleSettings -SubscriptionId $subid -RoleName $roleName -ExpireEligibleAssignmentsInDays 30 + +* (Preview) Credential Hygiene: + * We have introduced the concept of 'credential groups' wherein a set of credentials belonging to a specific application/functionality can be tracked together for expiry notifications. +* ARM Template Checker: + * N/A. + +* CICD: + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark + * N/A. + +* Log Analytics: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Support for AzSK-based telemetry (Log Analytics and Application Insights) features in Azure US Government and Azure China. + * Documentation covering end-to-end org policy scenarios with hands-on code examples will be published in the org policy section this week. + * Added support for org policy debug mode to extend ARM Checker controls. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Credential Hygiene helper cmdlets (from last sprint) + * New-AzSKTrackedCredential to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * Get-AzSKTrackedCredential to list the onboarded credential(s). + * Update-AzSKTrackedCredential to update the credential settings and reset the last updated timestamp. + * Remove-AzSKTrackedCredential to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * Set-AzSKPIMConfiguration for configuring/changing PIM settings + * Get-AzSKPIMConfiguration for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + setpim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +### Other improvements/bug fixes +* Subscription Security: + * N/A. +* SVTs: + * N/A. +* Controls: + * For the justify admins/owners control, the attested data will now show the sign-in names as well. + * Fixed CORS access and restricted IP callers controls for API Management which were previously throwing error. +* ARM Template Checker: + * Following new controls have been added to ARM Checker: + * Azure_AnalysisServices_BCDR_Plan + * Azure_AppService_DP_Use_Approved_TLS_Version + * Azure_ContainerRegistry_Configure_Webhook_For_Vuln_Scan + * Azure_ContainerRegistry_DP_Enable_Content_Trust + * Azure_RedisCache_BCDR_Use_RDB_Backup + * Azure_Search_AuthN_Use_Managed_Service_Identity + * Azure_VNet_NetSec_Configure_NSG + * Azure_VNet_NetSec_Justify_Peering + +* CA: + * N/A. + +* Privileged Identity Management (PIM) + * Fixed an issue where activating PIM role at resource level wasn't working before. + * While extending PIM assignments using the Set-AzSKPIMConfiguration cmdlet, if the provided assignment duration exceeds the maximum allowed days for assignment, the command will assign role only for the maximum allowed days. + * Assignment state of eligible roles will now be displayed when Get-AzSKPIMConfiguration cmdlet is used with -ListMyEligibleRoles switch. + +* Azure DevOps (ADO/VSTS) + * Configured and released AzSK module for Azure DevOps based on the restructured core framework. + +* Log Analytics + * N/A. + +* Other + * Updated the minimum required version for CA runbook, alerts and ARM policies. This can be verified for your subscription using the command Get-AzSKInfo -SubscriptionInfo. + diff --git a/ReleaseNotes/RN191015.md b/ReleaseNotes/RN191015.md new file mode 100644 index 00000000..d5774df7 --- /dev/null +++ b/ReleaseNotes/RN191015.md @@ -0,0 +1,113 @@ +## 191015 (AzSK v.4.2.0) + +### Feature updates + +* DevOps Kit controls expressed as Azure Policy (in progress): + * Authored Azure Policy for 30 more DevOps Kit controls. These will be submitted to the Azure Security Center (ASC) team for inclusion in the ASC initiative. + +* CICD: + * DevOps Kit CICD SVT task can now optionally also cover subscription security controls. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * In-cluster CA cmdlets (Install, Get, Update & Remove-CA) for AKS are now available in the main AzSK module. + * In-cluster CA now supports sending scan telemetry to log analytics (LA) workspace for AKS. This can be configured by using the ``` Install-AzSKContinuousAssuranceForCluster ``` cmdlet. + * Added 2 new in-cluster security controls for AKS. + + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Removed a check that was prohibiting use of custom-generated SPNs in central-mode CA. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Credential Hygiene helper cmdlets (from last sprint) + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +### Other improvements/bug fixes +* Subscription Security: + * N/A. + +* SVTs: + * Fixed an issue wherein fetching role assignments for Cloud Service Provider (CSP) subscriptions was resulting in an error (addresses the fact that CSP subscriptions do not have classic admins). + * Fixed a regression regarding telemetry for Env & ComponentId tags from security scans. + +* Controls: + * Azure Security Center (ASC) std-tier requirement control has been augmented to check pricing tier for individual resource types (Virtual Machines, App Services, SQL Servers & Storage accounts). + * The app service Managed Service Identity (MSI) control will now emit a ‘passed’ status (instead of ‘verify’) if MSI is enabled. + * The following new controls have been added to various SVTs: + * Azure_Storage_AuthN_Use_AAD_Based_Access + * Azure_Storage_AuthZ_Grant_Min_RBAC_Access + * Azure_Storage_AuthZ_Restrict_Network_Access + * Azure_Storage_BCDR_Enable_Soft_Delete + * Azure_KubernetesService_DP_Disable_HTTP_Application_Routing + +* ARM Template Checker: + * Following new controls have been added to ARM Checker: + * Azure_AnalysisServices_AuthZ_Min_Admin + * Azure_Databricks_AuthZ_Enable_Cluster_Access_Control + * Azure_Databricks_AuthZ_Enable_Job_Access_Control + * Azure_Databricks_AuthZ_Enable_Workspace_Access_Control + + +* CA: + * N/A. + +* Privileged Identity Management (PIM): + * Added support for assigning roles to multiple users when using the -AssignRole flag. + ``` + setpim -AssignRole -SubscriptionId $subid -RoleName $roleName -PrincipalName 'x@microsoft.com, y@microsoft.com, z@microsoft.com' -DurationInDays $days + ``` + + * Documentation representing an end-to-end workflow for AzSK PIM cmdlets will be published [here](https://github.com/azsk/DevOpsKit-docs/tree/master/01-Subscription-Security) this week. + + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. \ No newline at end of file diff --git a/ReleaseNotes/RN191115.md b/ReleaseNotes/RN191115.md new file mode 100644 index 00000000..f1e6d283 --- /dev/null +++ b/ReleaseNotes/RN191115.md @@ -0,0 +1,113 @@ +## 191115 (AzSK v.4.3.0) + +### Feature updates + +* DevOps Kit controls expressed as Azure Policy (in progress): + * Authored Azure Policy for 70 more DevOps Kit controls. These will be submitted to the Azure Security Center (ASC) team for inclusion in the ASC initiative. + * At this point we are done with 152 of approx. 250 controls. For most of the remaining controls from the target set, we are blocked for various reasons such as absence of alias, need custom code, etc. +* Security Verification Tests (SVTs): + * Added support for Azure Virtual Machine Scale Sets (VMSS). + * Automated controls include checks for anti-malware protection, monitoring, disk encryption, VM instance upgradation, IP configuration, NSG rules and diagnostic settings. + +* Privileged Identity Management (PIM): + * Added capabilities to enable conditional access policy for PIM in a subscription. This can be achieved using the following command: + + + ``` setpim -ConfigureRoleSettings -SubscriptionId $subid -RoleName $roleName -ApplyConditonalAccessPolicyForRoleActivation $true``` + * Added support for activation of permanent eligible PIM assignments. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A +* Log Analytics: + * N/A. +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Ported Org policy cmdlets to PS Core. After this change, users can perform all org policy management operations from OS X/Linux, etc. + * Validated support for use of a local folder on the client machine (as opposed to a storage-based blob) as the source for org policy at AzSK runtime. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim ```)for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim ```)for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +### Other improvements/bug fixes +* Subscription Security: + * Subscription security controls that check for persistent access viz. Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG and Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access will no longer fail for permanent PIM eligible roles. + * Introduced a new control Azure_Subscription_Configure_Conditional_Access_for_PIM to check that conditional access policy has been configured for subscription level critical roles (Owner, User Access Administrator and Contributor) in PIM as required by an org. + * Fixed a bug in the ``` Set-AzSKSubscriptionRBAC``` command where the missing mandatory RBAC accounts were not being added when not using the ```-Force``` parameter. + * Control for checking Azure Security Center (ASC) setup has been updated to limit checking desired ASC policy state (‘enabled’/’disabled’) only at the subscription scope. Validation and evaluation of assignments at management group scope will be available in a future release. + +* Privileged Identity Management (PIM): + * Fixed an issue where PIM access was getting activated on additional resource groups due to a more permissive regex match. + * Bug fix in ```Set-AzSKPIMConfiguration -RemovePermanentAssignments```. Earlier, the command used to give success message for unauthorised request, which has been fixed as part of this bug fix. + +* SVTs: + * N/A + +* Controls: + * Automated the control Azure_APIManagement_DP_Use_Secure_TLS_Version to detect if any of the unsecure protocols/cipher configurations (3DES Ciphers, TLS protocols 1.0/1.1 and SSL 3.0) are enabled in an APIM service. + * Azure_VirtualMachine_SI_Enable_Vuln_Solution control will now be skipped for VMs used in Kubernetes and Databricks clusters. This is to avoid noise for VMs that get spun up temporarily for job execution and then disappear. In future sprints, we plan to review some more candidate controls for such exclusion. + * Fixed an issue with the control Azure_VirtualMachine_SI_Deploy_GuestConfig_Extension where it was failing if both user and system-assigned identity were enabled on the VM resource. (The control was supposed to check only system-assigned identity.) + * The TLS control for AppService has been renamed from Azure_AppService_DP_Use_Approved_TLS_Version to Azure_AppService_DP_Use_Secure_TLS_Version. + +* ARM Template Checker: + * The following new controls have been added to ARM Checker: + * Azure_AppService_DP_Review_CORS_Request_Credential + * Azure_DBforMySQL_Authz_Enable_SSL_Connection + * Azure_DBforPostgreSQL_AuthZ_Enable_SSL_Connection + * Azure_Storage_BCDR_Enable_Soft_Delete + +* CA: + * N/A. + +* In-cluster CA: + * 2 new in-cluster security controls to check latest version of HDI 3.0 and Spark 2.4 + * Introduced a flag to retrieve and delete previous scan reports and metadata. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN191213.md b/ReleaseNotes/RN191213.md new file mode 100644 index 00000000..d5920efc --- /dev/null +++ b/ReleaseNotes/RN191213.md @@ -0,0 +1,122 @@ +## 191213 (AzSK v.4.4.0) + +### Feature updates + +* DevOps Kit controls expressed as Azure Policy (in progress): + * This sprint we focused on testing & fine-tuning some of our authored policies and also added clarifications for all the Azure PG task items in ADO (representing policies which are currently blocked for various reasons such as absence of alias, need custom code, etc.). + * (No new update for Dec) So far, we have authored policies for 152 of approx. 250 controls. + +* Security Verification Tests (SVTs): + * Added a new SVT for Azure Log Analytics. + +* Control attestation workflow has been enhanced so that the updated control status reflects immediately on the dashboard. This is accomplished by re-running the scan of recently attested controls as the last step of the attestation workflow. In the past, the user had to manually rescan or wait for the next CA scan results to reflect on the dashboard. + +* (Preview) AzSK module for Azure DevOps (ADO) + * Packaged the DevOps Kit scanner for ADO as a native ADO extension that can be used for continuous assurance for ADO security. This also includes widgets to visualize the scan results for various stakeholders (such as org admin, project owners, build/release owners etc.). + * Refer the documentation here for more information. + * You can also run the scanner in the native PowerShell mode using the instructions here. + + +* Privileged Identity Management (PIM): + * N/A + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A +* Log Analytics: + * N/A. +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Added capabilities to setup AzSK to scan subscriptions across multiple tenants. Instructions will be available [here](https://aka.ms/devopskit/crosstenant) early next week. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim ```)for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim ```)for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $s5 -DurationInHours 8 -Justification 'ad hoc test' -RoleName Owner ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +### Other improvements/bug fixes +* Subscription Security: + * Until last sprint, Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG control was being evaluated only via CA (because scanning the control for all RGs can take a lot of time.). We have now added support to query the result from CA scan and include it as a part of the local scan results. Moreover, if you want to force scan the actual control in local mode, you can do so by specifying the control id explicitly as shown in the command below: + + ```PowerShell + gss -s ‘’ -cid ‘Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG’ + + ``` + Note: Currently the PIM controls flag service accounts as well for persistent access. Due to limited access privilege of the CA service principal, we cannot determine if an account is a service account. As a result, we suggest using control attestation if you need to use service account in privileged roles. + +* Privileged Identity Management (PIM): + * N/A + +* SVTs: + * N/A + +* Controls: + * Until now, we were considering control results for snoozed/deallocated VMs as control failures immediately. To accommodate scenarios for temporary snoozing etc., we have added support to retain last actual scan results for VM controls for 7 days. Note that this means a VM should be scanned live either manually or via CA at least once every 7 days. + * Similarly, for clusters such as Kubernetes and Databricks, VMs that get spun up temporarily for job execution were being subject to full scan - resulting in dashboard churns. We have added exclusions for a subset of controls which may not make sense for such VMs. + * Auto-fix (-GenerateFixScript) feature is now available for the control Azure_AppService_DP_Use_Secure_TLS_Version. + + +* ARM Template Checker: + * The following new controls have been added to ARM Checker: + * Azure_DBforMySQL_AuthZ_Review_AzureServices_Access + * Azure_DBforMySQL_AuthZ_Verify_IP_Range + * Azure_DBforPostgreSQL_AuthZ_Review_AzureServices_Access + * Azure_DBforPostgreSQL_AuthZ_Verify_IP_Range + * Azure_VirtualMachineScaleSet_Deploy_Monitoring_Agent + * Azure_VirtualMachineScaleSet_SI_Enable_Antimalware + * Azure_VirtualMachineScaleSet_SI_Enable_Auto_OS_Upgrade + * Azure_VirtualMachineScaleSet_SI_Latest_Model_Applied + + +* CA: + * N/A. + +* In-cluster CA: + * Update-AzSKContinuousAssuranceForCluster has been optimized to update schedules and retain scan logs. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN200114.md b/ReleaseNotes/RN200114.md new file mode 100644 index 00000000..998cc4a7 --- /dev/null +++ b/ReleaseNotes/RN200114.md @@ -0,0 +1,133 @@ +## 200114 (AzSK v.4.5.0) + +### Feature updates + +* Continuous Assurance (CA) – Runbook throttling issues for large subscriptions: + * For the last few sprints, we had been investigating some recurrent issues which were causing CA runbook scans to abruptly terminate for a few CSEO subscriptions.The CA runbook scan happens inside a container that is deployed with certain memory, CPU, networking thresholds imposed by Azure Automation service runtime. If any of the thresholds are exceeded, Azure Automation terminates the container (and, as a result, the scan remains incomplete).While this was mostly happening in some of the larger subscriptions (several thousand resources), we were also observing the same symptoms in the occasional small subscription. + + * In the current sprint, we were able to identify and address most of the root causes leading to this resource exhaustion during CA scans. The fixes involved performance tuning at various layers (AzSK module code, control status/inventory reporting API, backend stored procedures, etc.). Furthermore, we improved the logic so that if the resource bottleneck was caused by a specific resource (e.g., a vNet with too many NIC configurations), we skip past that after a fixed number of retries. We also put in additional telemetry and diagnostic indications that would help us identify root causes quicker in future investigations. + + * As a result of these changes, more resources will become visible from a compliance standpoint. Additionally, due to optimization in the state saved, attestation for some controls may show a drift. Also, in a few cases, we may skip certain controls in CA if we find that the resources consumed would cause the scan to terminate. (We are looking at a container-based solution that might alleviate this issue.) + + * The following controls (belonging to respective resource types) were modified as part of this optimization effort: + * Virtual network (vNet,ErVNet) + * Azure_VNet_NetSec_Justify_PublicIPs + * Azure_VNet_NetSec_Justify_IPForwarding_for_NICs + * Azure_ERvNet_NetSec_Dont_Enable_IPForwarding_for_NICs + * Azure_ERvNet_NetSec_Dont_Use_PublicIPs + + * SQL Database + * Azure_SQLDatabase_Audit_Enable_Threat_Detection_Server + * Azure_SQLDatabase_Audit_Enable_Logging_and_Monitoring_Server + + * API Management + * Azure_APIManagement_DP_Restrict_CORS_Access + * Azure_APIManagement_AuthZ_Restrict_Caller_IPs + * Azure_APIManagement_AuthZ_Enable_Requires_Subscription + * Azure_APIManagement_DP_Remove_Default_Products + * Azure_APIManagement_DP_Restrict_Critical_APIs_Access + * Azure_APIManagement_AuthZ_Validate_JWT + * Azure_APIManagement_AuthZ_Enable_User_Authorization_For_API + + * Service Bus + * Azure_ServiceBus_AuthZ_Use_Minimum_Access_Policies + * SubscriptionCore + * Azure_Subscription_SI_Lock_Critical_Resources + + +* Security Verification Tests (SVTs): + * N/A. + +* Privileged Identity Management (PIM): + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Azure Security Center (ASC) alerts/notifications control will now fail for high severity alerts without any grace period considerations. It will also fail if there are medium severity alerts that have not been addressed for more than 30 days. + * Added a new control Azure_Subscription_Use_Only_Alt_Credentials to check PIM assignments for non SC-ALT accounts with critical privileges (user access admin, owner & contributor) at subscription scope. This control currently requires graph access on the subscription. + + +* Privileged Identity Management (PIM): + * N/A. + +* SVTs: + * N/A. + +* Controls: + * Fixed an issue to better handle BOM/special characters in control/metadata state. + + +* ARM Template Checker: + * Fixed an issue in checking the .NET framework version for app service ARM template in the control Azure_AppService_Deploy_Use_Latest_Version. + + +* CA: + * ``` Get-AzSKContinuousAssurance ``` cmdlet has been improved to check for suspended jobs (in the last 3 days) and automation runbook scan logs in the DevOps Kit storage account in the subscription. + +* In-cluster CA: + * N/A. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN200214.md b/ReleaseNotes/RN200214.md new file mode 100644 index 00000000..c55e944e --- /dev/null +++ b/ReleaseNotes/RN200214.md @@ -0,0 +1,135 @@ +## 200214 (AzSK v.4.6.0) + +### Feature updates + +* (Preview) DevOps Kit Continuous Assurance using containers: + * Public preview to run DevOps Kit CA runbook inside a container image (in lieu of Azure Automation hosted runbooks). + * This has been developed as an alternate option that is not limited by the memory, CPU and networking thresholds imposed by Azure Automation service runtime. Currently in larger subscriptions, if any of the thresholds are exceeded, Azure Automation terminates the sandbox and, as a result, the scan remains incomplete. + * This eliminates the need to renew the certificate periodically. + * Installation steps will be available [here](http://aka.ms/devopskit/containerizedCA) early next week. + + +* (Preview) AzSK module for Azure DevOps (ADO): + * Packaged the DevOps Kit scanner for ADO as a native ADO extension that can be used for Continuous Assurance for ADO security. This also includes widgets to visualize the scan results for various stakeholders (such as org admin, project owners, build/release owners etc.). + * The dashboard now supports link to failing resources for each control. + * Refer the documentation [here](https://github.com/azsk/DevOpsKit-docs/blob/master/09-AzureDevOps(VSTS)-Security/Readme.md#continuous-assurance-1) for more information. + * Added ~20 new security controls at organization, project, user, pipeline (build & release), service connection and agent pool scope. + * Added support to target scans using parameters/switches like baseline controls, control id & severity. + +* Security Verification Tests (SVTs): + * Introduced a new feature that lets us evaluate native DevOps Kit controls and the corresponding Azure policies (as available). + * This will be useful in our efforts to transition from DevOps Kit controls to native Azure policies. Currently, this is available as an opt-in capability. + +* Privileged Identity Management (PIM): + * –RemovePIMAssignment switch has been added in Set-AzSKPIMConfiguration cmdlet to remove PIM assignments of users for a specific role. E.g., + ```Powershell + setpim -RemovePIMAssignment -SubscriptionId $sub -RoleName ‘Owner’ -PrincipalNames ‘abc@microsoft.com,xyz@microsoft.com’ -Force + ``` + +* Control Attestation: + * Added capabilities to address situation where if the structure of the attested state for a resource is changed by DevOps Kit, the current control attestation will be respected till its actual expiry. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Added a view for resource inventory of an organization in the cloud security compliance report (using PowerBI). + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + +### Other improvements/bug fixes +* Subscription Security: + * Azure Security Center (ASC) setup umbrella control (which checks for auto provisioning, security contacts and policies configuration in the subscription) is now refactored into three new controls to validate each of these checks separately. + * Set-AzSKAzureSecurityCenterPolicies cmdlet has been enhanced to update auto provisioning and security policies status by default. Additionally, security contact email/phone will be updated only if provided additionally. + * Azure_Subscription_Use_Only_Alt_Credentials control can now check assignments (both permanent & PIM) for non SC-ALT accounts with critical privileges at subscription as well as resource group scope. This control can now be scanned in CA mode as well. + * Moreover, if you want to force scan the actual control in local mode, you can do so by specifying the control id explicitly as shown in the command below: + ```Powershell + gss -s $sub -cid ‘Azure_Subscription_Use_Only_Alt_Credentials’ + ``` + +* Privileged Identity Management (PIM): + * Updated the setpim cmdlet to use v2 APIs to configure PIM role settings. + * Fixed issue to remove permanent assignments for groups in the setpim cmdlet using the -RemovePermanentAssignments switch. + * Added support for principal name-based filtering in the setpim cmdlet for -AssignEligibleforPermanentAssignments and –RemovePIMAssignment switches. + * getpim cmdlet will now output list of roles in CSV format as well. + + +* SVTs: + * N/A. + +* Controls: + * Fixed antimalware control for VM which was previously reporting false positive results for Linux VMs. + * Fixed issues in the controls Azure_AppService_AuthZ_Configure_IP_Restrictions and Azure_ServiceFabric_DP_Dont_Expose_Reverse_Proxy_Port which were previously resulting into error. + * As a part of our efforts to resolve the CA runbook throttling issues for large subscriptions, the following APIM controls will be skipped in CA mode for an APIM resource having more than 30 associated APIs: + * Azure_APIManagement_DP_Restrict_CORS_Access + * Azure_APIManagement_AuthZ_Restrict_Caller_IPs + * Azure_APIManagement_AuthZ_Validate_JWT + * Azure_APIManagement_AuthZ_Enable_User_Authorization_For_API + + + +* ARM Template Checker: + * Fixed a bug where in a specific ARM template was failing the ARM Checker CICD task despite being compliant with all the applicable controls. + + +* CA: + * N/A. + +* In-cluster CA: + * N/A. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN200316.md b/ReleaseNotes/RN200316.md new file mode 100644 index 00000000..fa093549 --- /dev/null +++ b/ReleaseNotes/RN200316.md @@ -0,0 +1,120 @@ +## 200316 (AzSK v.4.7.0) + +### Feature updates + +* Privileged Identity Management (PIM): + * DevOps Kit PIM cmdlets now support PIM operations at management group scope. + + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings +```setpim -ActivateMyRole –ManagementGroupId $MGID -RoleName Reader -DurationInHours 8 -Justification 'ad hoc test'``` + + Similar operations can be performed for other switches like –AssignRole, -AssignEligibleforPermanentAssignments, -RemovePermanentAssignments, -ExtendExpiringAssignments and -RemovePIMAssignment in ```setpim``` command. + + + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status +```getpim -ListPIMAssignments –ManagementGroupId $MGID``` + + Similar operations can be performed for other switches like –ListPermanentAssignments and –ListSoonToExpireAssignments in ```getpim``` command. + + +* Az-* PowerShell libraries upgrade: + * This release of DevOps Kit has been updated to use the new Az-* PowerShell libraries (v.3.4.0). By and large, this should be a seamless transition for DevOps Kit users. + * We have also updated control recommendation, fix-scripts etc. to reflect the change due to this upgrade. + +* (Preview) AzSK module for Azure DevOps (ADO): + * Packaged the DevOps Kit scanner for ADO as a native ADO extension that can be used for Continuous Assurance for ADO security. This also includes widgets to visualize the scan results for various stakeholders (such as org admin, project owners, build/release owners etc.). + * Scan reports are now segregated by individual projects in the extension dashboard. + * Added support to target scans using parameters/switches like baseline controls & severity in the native ADO extension task. + * Resolved scalability issues to scan organizations with large number of projects/pipelines/service connections/agent pools. + +* Security Verification Tests (SVTs): + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * N/A. + +* Privileged Identity Management (PIM): + * N/A. + +* SVTs: + * N/A. + +* Controls: + * Fixed TLS enforcement control for App Service which was previously reporting false positive results. + * Fixed issues in the controls Azure_ServiceFabric_Audit_Use_Diagnostics_Log,Azure_ServiceFabric_DP_Exposed_Endpoint_SSL_Secured and Azure_ServiceFabric_DP_Dont_Expose_Reverse_Proxy_Port which were previously resulting into error. + + +* ARM Template Checker: + * N/A. + +* CA: + * N/A. + +* In-cluster CA: + * N/A. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN200415.md b/ReleaseNotes/RN200415.md new file mode 100644 index 00000000..a5782ef3 --- /dev/null +++ b/ReleaseNotes/RN200415.md @@ -0,0 +1,133 @@ +## 200415 (AzSK v.4.8.0) + +### Feature updates + +* Privileged Identity Management (PIM): + * Added a new switch -ConfigureRoleSettings in the setpim cmdlet to configure role settings at management group scope. + ```Powershell + setpim -ConfigureRoleSettings –ManagementGroupId $MGID -RoleName Reader -MaximumActivationDuration 7 -ExpireEligibleAssignmentsInDays 11 -RequireJustificationOnActivation $true -RequireMFAOnActivation $true + ``` + * Added a new switch -ListRoleSettings in the getpim cmdlet to list role settings in a subscription. + ```Powershell + getpim –ListRoleSettings -SubscriptionId $sub -RoleName Owner + ``` + * Added support in the setpim cmdlet to assign active roles to users. + ```Powershell + setpim -AssignRole – SubscriptionId $sub -RoleName Owner -DurationInDays 10 -PrincipalNames ‘abc@microsoft.com’ -AssignmentType Active + ``` + + + +* AzSK module for Azure DevOps (ADO): + * Introduced attestation feature that empowers users to support scenarios where human input is required to augment or override the default control evaluation status from the toolkit. + * Implemented via a new switch -ControlsToAttest which can be specified in any of the standard security scan cmdlets of the toolkit. + * Attestation is currently supported only for organization and project controls with admin privileges on organization and project, respectively. + * Currently, attestation can be performed only via PowerShell session in local machine, but the scan results will be honored in both local as well as extension scan. + * Added widget to visualize scan results of agent pools in a project. + * Scan reports are now segregated by individual projects and results for every build can be viewed individually in the extension dashboard. + * Scan reports can now also be downloaded from the build pipeline logs. + * Service connection parameter is no more mandatory to run the extension in pipeline. + * Enhanced a project control to evaluate different project visibility options. + * Fixed an issue in the control AzureDevOps_Organization_Review_Project_Collection_Accounts which was earlier reporting manual state for passed scenario. + * Fixed a bug with -UsePreviewBaselineControls switch which when used was scanning all the controls earlier. + * Baseline information of controls will now be displayed in scan reports. + * Note: The DevOps Kit scanner for ADO is also available as a native ADO extension that can be used for Continuous Assurance for ADO security. This also includes widgets to visualize the scan results for various stakeholders (such as org admin, project owners, build/release owners etc.). + + +* Security Verification Tests (SVTs): + * We have reviewed all AzSK controls and marked those that touch on network security (firewall, ports, etc.) with the 'NetSec' tag. You can target these controls using the -FilterTags 'NetSec' parameter. +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* (Preview) AzSK module for Azure DevOps (ADO/VSTS) + * You can try the scan cmdlet using: + ```Powershell + #VSTS scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Fixed an issue in the Set-AzSKAzureSecurityCenterPolicies cmdlet which was previously resulting into error for policy assignments explicitly set from the portal. + +* Privileged Identity Management (PIM): + * Switched to a different PIM API to address a timeout issue in the cmdlets. + +* SVTs: + * Fixed an issue with the behavior of -FilterTags switch which was not working as expected when used in conjugation with -UseBaselineControls switch. + * You can now combine the -UseBaselineControls and -FilterTags like below to scan just the controls that CA does not check: + ```Powershell + grs -s $subId -ubc -FilterTags OwnerAccess + ``` + + +* Controls: + * N/A + +* Privileged Identity Management (PIM): + * N/A + + +* ARM Template Checker: + * N/A. + +* CA: + * N/A. + +* In-cluster CA: + * N/A. + +* Azure DevOps (ADO/VSTS): + * N/A. + +* Log Analytics: + * N/A. + +* Other + * N/A. diff --git a/ReleaseNotes/RN200515.md b/ReleaseNotes/RN200515.md new file mode 100644 index 00000000..e9e57599 --- /dev/null +++ b/ReleaseNotes/RN200515.md @@ -0,0 +1,146 @@ +## 200515 (AzSK v.4.9.0) + +### Feature updates + +* Privileged Identity Management (PIM): + * Earlier, role settings could be configured only for eligible assignments via the setpim cmdlet. We have now expanded support to configure role settings for active assignments at subscription and management group scope by adding new parameters in the setpim cmdlet. + ```Powershell + setpim -ConfigureRoleSettings –SubscriptionId $sub -RoleName AcrPull -ExpireActiveAssignmentsInDays 11 -RequireJustificationOnActiveAssignment $true -RequireMFAOnActiveAssignment $true + + setpim -ConfigureRoleSettings –ManagementGroupId $MGID -RoleName AcrPull -ExpireActiveAssignmentsInDays 11 -RequireJustificationOnActiveAssignment $true -RequireMFAOnActiveAssignment $true + ``` + + +* AzSK module for Azure DevOps (ADO): + + * Introduced custom organization policy feature for central security team of an organization to customize the behavior of various functions and security controls checked by the ADO scanner. This enables project admins to create a policy store and other required components to host and maintain a set of policy files that allow customization of the ADO scanner controls and feature behavior. + + * Revamped attestation feature to leverage repos in Azure DevOps for storing control attestation details. + * Introduced a new switch -AttestationHostProjectName to specify the project name for storing attestation details for organization-specific controls. + * Implemented via switch -ControlsToAttest which can be specified in any of the standard security scan cmdlets of the scanner. + * Added support for attestation of build, release, service connection and agent pool controls. + * Organization and project controls can now also be attested via their individual scan cmdlets Get-AzSKAzureDevOpsOrgSecurityStatus and Get-AzSKAzureDevOpsProjectSecurityStatus respectively. + * Note that attestation for organization and project controls can only be performed with admin privileges on organization and project, respectively + * Currently, attestation can be performed only via PowerShell session in local machine, but the scan results will be honored in both local as well as extension scan. + * Added aliases for individual scan cmdlets for organization, project, build, release, service connection and agent pool. + ```Powershell + gadso -oz "MicrosoftIT" #Organization-specific controls scan + + gadsp -oz "MicrosoftIT" -pn "OneITVSO" #Project-specific controls scan + + ``` + * Updated the resource link for user-specific controls. + + +* ADO Security Scanner extension:: + + * Build and release parameters are no more mandatory to run the extension in pipeline. + * ‘Exception’ status will now be represented in widgets for build, release, service connection and agent pool controls. + * Note: Security scanner for ADO is also available as a native ADO extension that can be used for Continuous Assurance for ADO security. This also includes widgets to visualize the scan results for various stakeholders (such as org admin, project owners, build/release owners etc.). + + + + +* Security Verification Tests (SVTs): + * N/A. +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Fixed an issue in the Set-AzSKARMPolicies cmdlet which was previously not able to create policy assignment if its definition was already present in the subscription. + +* Privileged Identity Management (PIM): + * N/A. + +* SVTs: + * Fixed a bug in bulk attestation workflow where previously all the targeted controls were being attested with the same status and justification. Now, -ControlIds parameter is made mandatory and only one control can be bulk attested across resources at a time. + + + +* Controls: + * Resolved an issue in the subscription ARM policy control to emit failed status if the ARM policy assignment is disabled in the subscription. + * Added a new control Azure_AppService_AuthN_Redirect_To_Login_Page to check whether authentication is configured at root page of an app service. + * Virtual machine guest policy health control has been updated to check for compliance of guest policies and initiatives as configured via organization policy. Previously, the control used to check compliance for all health policies deployed on the machine. + +* ARM Template Checker: + * N/A. + +* CA: + * N/A. + +* In-cluster CA: + * N/A. + +* Security scanner for Azure DevOps (ADO): + + * Control for installed extensions in an organization will filter out built-in extensions from scans. + * Project visibility control will now pass when either ‘Private’ or ‘Enterprise’ visibility is enabled for the project. + * Fixed an issue in the control + AzureDevOps_Build_AuthZ_Disable_Inherited_Permissions which was earlier reporting failed state even when the inherited permissions on the pipeline were disabled. + * Trimmed state data for organization and project baseline controls without impacting its meaning. + * Fixed a bug where previously attestation drift was not being detected in a scenario in some stateful controls. + * Rectified tags for organization and project controls. + * Control settings file has been trimmed to make it relevant only to the ADO scanner (removed Azure-specific residues). + * Fixed an issue in Get-AzSKAzureDevOpsProjectSecurityStatus cmdlet to make the -ProjectNames parameter mandatory. + +* Log Analytics: + * N/A. + +* Known issues: + * Late in the test pass, we found that below Cosmos DB controls are resulting into error due to recent API changes: + * Azure_CosmosDB_AuthZ_Enable_Firewall + * Azure_CosmosDB_AuthZ_Verify_IP_Range diff --git a/ReleaseNotes/RN200615.md b/ReleaseNotes/RN200615.md new file mode 100644 index 00000000..2d6b5207 --- /dev/null +++ b/ReleaseNotes/RN200615.md @@ -0,0 +1,112 @@ +## 200615 (AzSK v.4.10.0) + +### Feature updates + +* Privileged Identity Management (PIM): + * Earlier, role settings could be listed only for eligible assignments via the getpim cmdlet. We have now expanded support to list role settings for active assignments as well at subscription and management group scope. + ```Powershell + getpim –ListRoleSettings -SubscriptionId $sub -RoleName Owner + + getpim –ListRoleSettings -ManagementGroupId $MGID -RoleName Owner + ``` + +* Security scanner for Azure DevOps (ADO)/ADO Security Scanner extension: + + * Introduced alerting and monitoring solution to empower individual teams to view control status of their project components. + + * Scanner now supports checkpointing for large scans via a -UsePartialCommits switch. + * Added support for bulk attestation feature which empowers teams to provide a common justification for a set of resources all of which have a specific (single) control id that requires attestation. + * ADO security scanner extension can now be used in release pipelines as well. + +* Security Verification Tests (SVTs): + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Added support for configuring non-AAD identity providers for app service. Refer [here](https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/OrgPolicyUpdate.md) for more information. + * Fixed an issue in SVT extension framework wherein extended class were not being correctly applied across resources of the same type. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Added Azure_Subscription_Configure_Conditional_Access_for_PIM_RG control to check whether conditional access policy for critical roles (User Access Administrator/Owner) is configured at resource group scope. + +* Privileged Identity Management (PIM): + * N/A. + +* SVTs: + * Fixed a bug in attestation workflow where previously if there was no previous attestation history in the subscription and multiple controls were being targeted for attestation, then only the first control in the list was being attested. + +* Controls: + * Anonymous blob access control is now enabled for Data Lake Storage Gen2 resources. + * Multiple controls have been enabled for APIM resources configured in consumption tier. These controls check for least access privileges, HTTPS enablement, CORS access, MSI, etc. on consumption tier APIM resources. + * Controls Azure_APIManagement_AuthN_Use_AAD_for_Client_AuthN and Azure_APIManagement_DP_Dont_Checkin_Secrets_In_Source will now emit manual status for APIM resources where port 3443 is restricted. + * Azure_KeyVault_AuthN_Dont_Share_KeyVault_Unless_Trust will now check for shared access on key vaults for enterprise applications apart from AAD applications. + * Resolved issues in firewall and IP controls for CosmosDB which were earlier resulting into error state due to recent API changes. + * Trimmed state data of virtual network peering control for ExpressRoute-connected VMs which was previously causing unwanted state drift due to changes unrelated to peering. + +* ARM Template Checker: + * N/A. + +* CA: + * N/A. + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A. + +* Known issues: + * N/A. diff --git a/ReleaseNotes/RN200715.md b/ReleaseNotes/RN200715.md new file mode 100644 index 00000000..d213ee08 --- /dev/null +++ b/ReleaseNotes/RN200715.md @@ -0,0 +1,128 @@ +## 200715 (AzSK v.4.11.0) + +### Feature updates + +* Management of DevOps Kit-based AAD applications: + * Added support for listing all the DevOps Kit-based service principals (used in continuous assurance) that are owned by the user via the Get-AzSKInfo cmd. It will list all such applications that have been actively in use. + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security scanner for Azure DevOps (ADO)/ADO Security Scanner extension: + + * Introduced capability to log bugs in ADO for control failures of your ADO resources. + * Added a dashboard in Log Analytics to support alerting and monitoring for ADO resources across the organization. + * Check-pointing behavior has been enhanced to support durable (server-based) checkpoints. + * Control attestation workflow has been enhanced so that the updated control status reflects immediately on the extension dashboard/log analytics workspace. + * Added soft protection to restrict users from scanning larger number of resources (>1000) in an organization + +* Security Verification Tests (SVTs): + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * Added SVT for ‘public IP address’ as a service to optionally treat each public IP address as an individual resource. To enable this behavior, refer the docs here. + * Fixed an issue to enable Get-AzSKOrganizationPolicyStatus command to work in Linux-based containers. + * Key Vault, CDN and Databricks control JSON files have been sanitized to remove hidden BOM/extended characters. Org policy admins should procure a fresh copy of these files from the module and replicate the overridden changes (if any). + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * The subscription controls below will not be evaluated in local scan mode unless the corresponding control ids are specified explicitly in the command. This is done because these controls require substantial amount of time for evaluation. + + * Azure_Subscription_Configure_Conditional_Access_for_PIM_RG + * Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG + * Azure_Subscription_Use_Only_Alt_Credentials + ```Powershell + gss -s $sub -cid ‘Azure_Subscription_AuthZ_Dont_Grant_Persistent_Access_RG’ + ``` + + * Results of persistent access (PIM) controls for subscription and resource group scope will not fluctuate in case the underlying API call throws exception. + +* Privileged Identity Management (PIM): + * Fixed an issue regarding activation of PIM role assignments where previously it was leading to an error if the role was assigned for the same scope for both direct and group assignments. + +* SVTs: + * N/A. + +* Controls: + * States for below controls will not fluctuate if they are scanned with insufficient permissions (leading to manual control state): + + * Azure_AppService_DP_Website_Load_Certificates_Not_All + * Azure_AppService_DP_Restrict_CORS_Access + * Azure_AppService_AuthN_Use_Managed_Service_Identity + * Azure_KeyVault_AuthN_Dont_Share_KeyVault_Unless_Trust + * Azure_KeyVault_AuthN_Use_Cert_Auth_for_Apps + + * Trimmed state data of public IP address control for VMs which was previously causing unwanted state drift due to data fields unrelated to IP address. + + * Spelling errors in two controls below have been fixed: + + * Azure_DataFactory_AuthN_DataLakeStore_LinkedService + * Azure_DataFactory_BCDR_Multiple_Node_DMG + +* ARM Template Checker: + * N/A. + +* CA: + * Fixed an issue in the CA check-pointing logic in scenarios where previously if a resource type does not have any applicable/enabled controls, CA scans were getting stuck at that resource. + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A. + +* Known issues: + * N/A. diff --git a/ReleaseNotes/RN200817.md b/ReleaseNotes/RN200817.md new file mode 100644 index 00000000..f148ed7b --- /dev/null +++ b/ReleaseNotes/RN200817.md @@ -0,0 +1,129 @@ +## 200817 (AzSK v.4.12.0) + +### Feature updates + +* Security scanner for Azure DevOps (ADO)/ADO Security Scanner extension: + + * Introducing an Azure-based continuous assurance scanning solution for ADO. The scanning infrastructure of this containerized model will be hosted in an Azure resource group. + * Added support for creating workbook-based dashboards in Log Analytics to support alerting and monitoring for ADO resources across the organization. + * Introduced Get-AzSKADOInfo command to provide overall information about the ADO security scanner which includes security controls information (severity, description, rationale, baseline etc.) and host information (ADO scanner settings/configuration, logged-in ADO user context etc.). + ```Powershell + Get-AzSKADOInfo –InfoType ControlInfo + Get-AzSKADOInfo –InfoType HostInfo + ``` + * Added support for auto-updating the scanner module whenever a new version is available. + * Added 17 new security controls at organization, project, user, pipeline (build & release), service connection and agent pool scope. + + +* Security Verification Tests (SVTs): + * N/A. + +* In-cluster security scans for ADB, AKS, HDI Spark: + * N/A. + +* Log Analytics: + * N/A. + +* ARM Template Checker: + * N/A. + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Management of DevOps Kit-based AAD applications: + * You can list all the DevOps Kit-based service principals (used in continuous assurance) that are owned by you via the Get-AzSKInfo cmd marking those that are actively used for CA scans. + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Behavior of subscription control to validate security contacts setup in Azure Security Center (ASC) has been updated to check the following configurations: + * At least one contact email should be configured. + * Alert notifications should be configured to be sent at least to Owner and Service Admin roles. + * Notifications should be enabled with a minimum severity of medium. + + +* Privileged Identity Management (PIM): + * -ExtendExpiringAssignments flag in setpim cmdlet has been updated to use -RoleName as the only parameter to specify the role name for which expiring assignments need to be extended. Earlier, -RoleNames was also allowed as a valid parameter in some scenarios. + ```Powershell + setpim -ExtendExpiringAssignments –SubscriptionId $sub -RoleName Reader -DurationInDays 60 -ExpiringInDays 10 + + setpim -ExtendExpiringAssignments –SubscriptionId $sub -RoleName Reader -DurationInDays 60 -PrincipalNames 'abc@microsoft.com' + ``` + +* CICD: + * DevOps Kit CICD SVT extension task will now exclude controls that require either owner access or role-based access control (RBAC) information from its scan by default. + + +* SVTs: + * Azure Databricks controls will be skipped in local scan mode unless a personal access token (PAT) is provided as described [here](https://aka.ms/azsk/scanadbresource). + * Fixed an issue related to control attestation where earlier difference in character casing of resource id between attested and current state was causing attestation drift. + + +* Controls: + * Behavior of Azure_CDN_DP_Enable_Https control has now been enhanced to allow both HTTP and HTTPS protocols for CDN endpoints (via an additional check to configure HTTP to HTTPS redirect rule). + * Fixed a bug to evaluate the diagnostics setting control of automation account correctly when multiple Log Analytics workspaces are configured. + * Disk encryption control will not be evaluated for VMs with ephemeral OS disk (these disks do not support disk encryption). + + +* ARM Template Checker: + * N/A. + +* CA: + * Added an extra check in Get-AzSKContinuousAssurance command to warn users if the CA certificate is about to expire in seven days. + * CA will now periodically (every 30 days) purge index entries for resources from the attestation history which do not exist anymore. This done to improve performance and reduce execution time in all scan modes. + + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A. + +* Others: + * Detailed security data for each evaluated control (SecurityEvaluationData.json) will not be generated by default after scan completion. If organizations wish to generate this file, organization policy owner need to update their server-based control settings by adding GenerateSecurityEvaluationJsonFile flag with its value set to true. diff --git a/ReleaseNotes/RN200915.md b/ReleaseNotes/RN200915.md new file mode 100644 index 00000000..967838ae --- /dev/null +++ b/ReleaseNotes/RN200915.md @@ -0,0 +1,149 @@ +## 200915 (AzSK v.4.13.0) + +### Feature updates + +* CA SPN old credentials cleanup: + + * When the below command is run to renew CA certificate, a new workflow will offer to delete existing old credentials: + ```Powershell + Update-AzSKContinuousAssurance –sid $sub -RenewCertificate + ``` + + * The ```-SkipCertificateCleanup``` switch may be used to skip deletion of older certificates. + + +* Security scanner for Azure DevOps (ADO)/ADO Security Scanner extension: + + * The key highlights for the Azure DevOps (ADO) security scanner release are (a) durable check-pointing for Azure hosted continuous assurance scans, (b) interfacing bug logging feature with service tree data and (c) renaming the module/extension/cmdlets/controls/features etc. from ‘AzureDevOps’ to ‘ADO’. With this release, ADO scanner is ready for CSEO-wide deployment. + * [Click here](https://idwebelements/GroupManagement.aspx?Group=azskadop&Operation=join) to subscribe to get detailed feature updates of ADO security scanner. + + +* Security Verification Tests (SVTs): + * N/A. + + +* Log Analytics: + * N/A. + + +* ARM Template Checker: + * N/A. + + +* Org policy/external user updates (for non-CSEO users): + * N/A. + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Management of DevOps Kit-based AAD applications: + * You can list all the DevOps Kit-based service principals (used in continuous assurance) that are owned by you via the Get-AzSKInfo cmd marking those that are actively used for CA scans. + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * Added support for configuring standard pricing tiers for all the resource types supported in Azure Security Center (ASC) via the ```-SetASCTier``` switch in the Set-AzSKAzureSecurityCenterPolicies cmd. + ```Powershell + Set-AzSKAzureSecurityCenterPolicies -SubscriptionId $sub -SetASCTier + ``` + +* Added four controls to strengthen the subscription RBAC hygiene: + * ```Azure_Subscription_Cleanup_Deleted_Object_Access``` control checks for deleted identities having access on subscription. + * ```Azure_Subscription_Remove_Access_For_Orphaned_Applications``` control checks for orphaned applications (without any owner) having access on subscription. + * ```Azure_Subscription_Check_Indirect_Access_Via_Applications``` control checks for applications with privileged roles but their owners do not have any access in subscription. + * ```Azure_Subscription_Review_Inactive_Identities``` control checks for identities that have been inactive in the subscription over the past 90 days. + + Note: These controls require owner access to subscription and will not be evaluated via continuous assurance. + +* SVTs: + * In keeping with the change in frequency of SDL cycle, attestation expiry period of the below controls has been updated to 180 days. + * Azure_APIManagement_AuthN_Verify_Delegated_Authentication + * Azure_AppService_AuthN_Use_AAD_for_Client_AuthN + * Azure_Automation_DP_Use_Encrypted_Variables + * Azure_APIManagement_DP_Dont_Checkin_Secrets_In_Source + * Azure_CloudService_AuthN_Use_AAD_for_Client_AuthN + * Azure_ContainerInstances_AuthZ_Container_Segregation + * Azure_KeyVault_AuthN_Dont_Share_KeyVault_Unless_Trust + * Azure_LoadBalancer_NetSec_Justify_PublicIPs + * Azure_NotificationHub_AuthZ_Dont_Use_Manage_Access_Permission + * Azure_VirtualMachine_NetSec_Justify_PublicIPs + * Fixed an issue in attestation feature where, for some controls, attestation drift was occurring if the current state of the control was a subset of the attested state. + +* Controls: + * Fixed an issue in the AAD authentication control for APIM which was resulting in error state due to a recent change in the underlying PG API. + * Control to check for resource locks on ExpressRoute-connected virtual network RG will now pass if either ‘read-only’ or ‘do-not-delete’ lock is configured. Earlier, the control used to check for only the read-only lock. + * AAD authentication control for AKS will also support the new AKS-managed authentication. + * Management port control for AKS will now check for open ports in both VM and VMSS-based backend pools. + * The Azure_CDN_DP_Enable_Http control has been updated to check for both temporary and permanent redirect rules. + * Antimalware and vulnerability solution controls for VM will now pass if the equivalent ASC assessment is ‘NotApplicable’. + * AAD authentication control for Linux-based function apps will pass if no HTTP trigger-based functions are defined in the app. + + +* Privileged Identity Management (PIM): + * N/A. + + +* CICD: + * N/A. + + +* ARM Template Checker: + * N/A. + +* CA: + * Fixed an issue in the Get-AzSKContinuousAssurance which was previously throwing an exception when scanned with reader permissions on the subscription. + + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A. + +* Others: + * Fixed bugs in: + (a) Get-AzSKInfo -InfoType ControlInfo and + (b) Get-AzSKControlStatus -FilterTags which was previously resulting into error due to internal caching of policy files. diff --git a/ReleaseNotes/RN201015.md b/ReleaseNotes/RN201015.md new file mode 100644 index 00000000..7ae3eb54 --- /dev/null +++ b/ReleaseNotes/RN201015.md @@ -0,0 +1,137 @@ +## 201015 (AzSK v.4.14.0) + +### Feature updates + +* CA SPN old credentials cleanup: + + * In the previous sprint, we had added support for deleting older certificate credentials when renewing the certificate for AzSK CA SPN. To allow users to request just deletion of older credentials (without necessarily renewing the current credential), we have added the -DeleteOldCredentials switch as under: + + ```Powershell + Update-AzSKContinuousAssurance –sid $sub -DeleteOldCredentials + ``` + + +* Security scanner for Azure DevOps (ADO)/ADO Security Scanner extension: + + * The key highlights for the Azure DevOps (ADO) security scanner release are support for (a) setting up Azure-hosted continuous assurance scans with Owner access only at the target RG level, (b) scanning all resources associated with a specific service and (c) various admin control improvements. This release has been deployed for CSEO-wide consumption and a dashboard is available at https://aka.ms/adoscanner/dashboard. + * [Click here](https://idwebelements/GroupManagement.aspx?Group=azskadop&Operation=join) to subscribe to get detailed feature updates of ADO security scanner. + + + +* Security Verification Tests (SVTs): + * N/A. + + +* Log Analytics: + * N/A. + + +* ARM Template Checker: + * N/A. + + +* Org policy/external user updates (for non-CSEO users): + * Added support to enable/disable anonymous usage telemetry for CA and CICD scans. + * For CA, this can be done by using -UsageTelemetryLevel flag as below: + + ```Powershell + Update-AzSKContinuousAssurance –sid $sub -UsageTelemetryLevel None + ``` + + * For CICD, a ‘UsageTelemetryLevel’ pipeline variable can be set to ‘None’ in the pipeline definition. + * For either case, the value Anonymous can be used to re-enable usage telemetry. + + * Note that, in local usage mode, this facility was always available via the command below: + + ```Powershell + Set-AzSKUsageTelemetryLevel -Level None + ``` + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Management of DevOps Kit-based AAD applications: + * You can list all the DevOps Kit-based service principals (used in continuous assurance) that are owned by you via the Get-AzSKInfo cmd marking those that are actively used for CA scans. + + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from last sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * NA + +* SVTs: + * Going forward, control attestation using older modules will be blocked in non-SAW environments. + +* Controls: + * Fixed an issue in the TLS control for APIM which was earlier reporting incorrect result for resources in consumption tier. + * Fixed an issue in Azure_CDN_DP_Enable_HTTPS control which was earlier resulting into error state for ‘Verizon’ and ‘Akamai’ options. + +* Privileged Identity Management (PIM): + * N/A. + +* CICD: + * N/A. + +* ARM Template Checker: + * N/A. + +* CA: + * Added support to display the currently in-use service principal name in the output of ```Get-AzSKContinuousAssurance``` command. + +* In-cluster CA: + * N/A. + +* Log Analytics: + * Added support for the -Force switch so that Log Analytics based monitoring solution can be installed using ```Install-AzSKMonitoringSolution``` without user interaction/consent if a view with the same name already exists. + +* Others: + * Fixed a bug in ```Get-AzSKInfo -InfoType ControlInfo``` when run with -UseBaselineControls/-UsePreviewBaselineControls/-FilterTags flags was previously resulting into error due to internal caching of policy files. + * Behavior of ```Get-AzSKInfo -InfoType ControlInfo``` has been rectified to report information of public IP address controls only when an org has enabled their evaluation. + * Fixed an issue in credential hygiene cmdlets where alerts for credentials nearing expiry were not triggered due to change in the underlying product API. + * ```Get-AzSKExpressRouteNetworkSecurityStatus``` command will not throw exception even if no control ids are specified. + diff --git a/ReleaseNotes/RN210115.md b/ReleaseNotes/RN210115.md new file mode 100644 index 00000000..715d42e6 --- /dev/null +++ b/ReleaseNotes/RN210115.md @@ -0,0 +1,121 @@ +## 210115 (AzSK v.4.15.0) + +### Feature updates + +* Default TLS 1.2 setting for AzSK storage account: + + * The storage account created under AzSKRG while installing CA using Install-AzSKContinuousAssurance command,will now be set up with ‘TLS version 1.2’ and ‘Allow Blob public access’ set to ‘Disabled’ by default.In order to apply these settings to your existing AzSK storage accounts, you’ll need to run following command: + ```Powershell + Update-AzSKContinuousAssurance -SubscriptionId $SubscriptionId + ``` + +* Security Verification Tests (SVTs): + * N/A. + + +* Log Analytics: + * N/A. + + +* ARM Template Checker: + * N/A. + + +* Org policy/external user updates (for non-CSEO users): + * Storage account created as part of Org policy setup via Install-AzSKOrganizationPolicy command will now be set up with TLS version 1.2 by default.To apply this setting for your existing org policy storage accounts, you just need to run following command: + ```Powershell + Update-AzSKOrganizationPolicy -SubscriptionId ` + -OrgName "Contoso" ` + -DepartmentName "IT" ` + -PolicyFolderPath "D:\ContosoPolicies" + + ``` + +Note: The next few items mention features from recent releases retained for visibility in case you missed those release announcements: + +* Management of DevOps Kit-based AAD applications: + * You can list all the DevOps Kit-based service principals (used in continuous assurance) that are owned by you via the Get-AzSKInfo cmd marking those that are actively used for CA scans. + + ```Powershell + Get-AzSKInfo –InfoType SPNInfo + ``` + +* Security Scanner for Azure DevOps (ADO) + * You can try the scan cmdlet using: + + ```Powershell + #ADO scan cmdlet is in a separate module called AzSK.AzureDevOps! + Install-Module AzSK.AzureDevOps -Scope CurrentUser -AllowClobber + Get-AzSKAzureDevOpsSecurityStatus -OrganizationName "MicrosoftIT"` + -ProjectNames "OneITVSO"` + -BuildNames "build_name_here"` + -ReleaseNames "release_name_here" + ``` + +* Credential Hygiene helper cmdlets + * ```New-AzSKTrackedCredential``` to onboard a credential for tracking via DevOps Kit. You can set the reminder period (in days) for the credential. + * ```Get-AzSKTrackedCredential``` to list the onboarded credential(s). + * ```Update-AzSKTrackedCredential``` to update the credential settings and reset the last updated timestamp. + * ```Remove-AzSKTrackedCredential``` to deboard a credential from AzSK tracking. + +* Privileged Identity Management (PIM) helper cmdlets (from earlier sprint) + * ```Set-AzSKPIMConfiguration``` (alias ```setpim```) for configuring/changing PIM settings + * ```Get-AzSKPIMConfiguration``` (alias ```getpim```) for querying various PIM settings/status + * Activating your PIM role is now as simple as this: + + ``` setpim -ActivateMyRole -SubscriptionId $sub -RoleName Owner -DurationInHours 8 -Justification 'ad hoc test' ``` + * See docs [here](https://github.com/azsk/DevOpsKit-docs/blob/master/01-Subscription-Security/Readme.md#azsk-privileged-identity-management-pim-helper-cmdlets-1) for more. + +* (Preview) Security Scan for Azure Active Directory (AAD) + * You can scan security controls for your AAD tenant (as either an admin or even as a regular user) using the DevOps Kit AAD Security Scan module. + * Use following steps: + + ```Powershell + # AAD scan cmdlets are packaged as a separate module (AzSK.AAD) + Install-Module AzSK.AAD -Scope CurrentUser -AllowClobber + Import-Module AzSK.AAD + Get-AzSKAADSecurityStatusTenant # check the tenant (admin) + Get-AzSKAADSecurityStatusUser # check objects you own (user) + ``` + * Caveats: + * Do not run these in the same PS session as AzSK. Start a new PS console. + * Az- modules require .Net Framework v4.7.2. + * By default, the current cmdlets will scan just 3 objects of each type (Apps/SPNs/Groups, etc.). This is until we work out how best to group/batch scans when scanning the entire tenant. If you want to scan more objects you can use the '-MaxObj' switch in the cmdlets. + + + +### Other improvements/bug fixes +* Subscription Security: + * N/A + +* SVTs: + * N/A + +* Controls: + * Fixed a bug in control ‘Azure_Subscription_AuthZ_Limit_ClassicAdmin_Count’. It will now fail in case there is an account having multiple classic admin roles e.g. account having both CoAdministrator and AccountAdministrator role + * Fixed a bug in control 'Azure_Subscription_Configure_Conditional_Access_for_PIM. The Control will flag roles that have conditional accesss policy configured but do not have required acrs tag. Expected tags are {"acrsRequired":true,"acrs":"urn:microsoft:req1"}. + * Fixed a bug in control Azure_SQLDatabase_DP_Enable_TDE. Now the control will pass if email notifications to either admins or to specific recipients are configured. + + +* Privileged Identity Management (PIM): + * N/A. + +* CICD: + * N/A. + +* ARM Template Checker: + * N/A. + +* CA: + * N/A + +* In-cluster CA: + * N/A. + +* Log Analytics: + * N/A + +* Others: + * N/A + + diff --git a/ReleaseNotes/toc.yml b/ReleaseNotes/toc.yml new file mode 100644 index 00000000..e81d2ebb --- /dev/null +++ b/ReleaseNotes/toc.yml @@ -0,0 +1,110 @@ +- name: Latest Release Notes + href: LatestReleaseNotes.md +- name: 210115 + href: RN210115.md +- name: 201015 + href: RN201015.md +- name: 200915 + href: RN200915.md +- name: 200817 + href: RN200817.md +- name: 200715 + href: RN200715.md +- name: 200615 + href: RN200615.md +- name: 200515 + href: RN200515.md +- name: 200415 + href: RN200415.md +- name: 200316 + href: RN200316.md +- name: 200214 + href: RN200214.md +- name: 200114 + href: RN200114.md +- name: 191213 + href: RN191213.md +- name: 191115 + href: RN191115.md +- name: 191015 + href: RN191015.md +- name: 190916 + href: RN190916.md +- name: 190814 + href: RN190814.md +- name: 190715 + href: RN190715.md +- name: 190614 + href: RN190614.md +- name: 190515 + href: RN190515.md +- name: 190415 + href: RN190415.md +- name: 190315 + href: RN190315.md +- name: 190215 + href: RN190215.md +- name: 190116 + href: RN190116.md +- name: 181217 + href: RN181217.md +- name: 181115 + href: RN181115.md +- name: 181015 + href: RN181015.md +- name: 180927 + href: RN180927.md +- name: 180917 + href: RN180917.md +- name: 180814 + href: RN180814.md +- name: 180716 + href: RN180716.md +- name: 180618 + href: RN180618.md +- name: 180515 + href: RN180515.md +- name: 180416 + href: RN180416.md +- name: 180315 + href: RN180315.md +- name: 180215 + href: RN180215.md +- name: 180115 + href: RN180115.md +- name: 171130 + href: RN171130.md +- name: 171031 + href: RN171031.md +- name: 170928 + href: RN170928.md +- name: 170831 + href: RN170831.md +- name: 170731 + href: RN170731.md +- name: 170630 + href: RN170630.md +- name: 170531 + href: RN170531.md +- name: 170428 + href: RN170428.md +- name: 170331 + href: RN170331.md +- name: 170223 + href: RN170223.md +- name: 170127 + href: RN170127.md +- name: 161223 + href: RN161223.md +- name: 161209 + href: RN161209.md +- name: 161125 + href: RN161125.md +- name: 161111 + href: RN161111.md +- name: 161028 + href: RN161028.md +- name: 161014 + href: RN161014.md +- name: 160930 + href: RN160930.md diff --git a/Videos/videos.md b/Videos/videos.md index 0a70174a..1a901408 100644 --- a/Videos/videos.md +++ b/Videos/videos.md @@ -1,3 +1,6 @@ +## IMPORTANT: DevOps Kit (AzSK) is being sunset by end of FY21. More details [here](/ReleaseNotes/AzSKSunsetNotice.md) +---------------------------------------------- + # Getting started with "The Secure DevOps Kit for Azure" Video Library!
    diff --git a/WebsiteContent/articles/toc.yml b/WebsiteContent/articles/toc.yml index 037a3160..c77b07a7 100644 --- a/WebsiteContent/articles/toc.yml +++ b/WebsiteContent/articles/toc.yml @@ -8,6 +8,8 @@ items: - name: Azure Service Security href: ../../00b-Getting-Started/GettingStarted_AzureServiceSecurity.md + - name: PowerShell tips for new AzSK Users + href: ../../00b-Getting-Started/GettingStarted_PowerShellTipsAzSK.md - name: Subscription Security href: ../../00b-Getting-Started/GettingStarted_SubscriptionSecurity.md - name: Addressing Control Failures @@ -20,24 +22,32 @@ - name: Control Coverage href: ../../02-Secure-Development/ControlCoverage/README.md items: - - name: AzSDK ARM PolicyList - href: ../../02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md - - name: AzSDK Alert List + - name: AzSK ARM PolicyList href: ../../02-Secure-Development/ControlCoverage/Feature/ARMPolicyList.md + - name: AzSK Alert List + href: ../../02-Secure-Development/ControlCoverage/Feature/AlertList.md - name: Analysis Services href: ../../02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md - name: App Service href: ../../02-Secure-Development/ControlCoverage/Feature/AppService.md + - name: Application Proxy + href: ../../02-Secure-Development/ControlCoverage/Feature/ApplicationProxy.md - name: Automation href: ../../02-Secure-Development/ControlCoverage/Feature/Automation.md - name: Batch href: ../../02-Secure-Development/ControlCoverage/Feature/Batch.md + - name: Bot + href: ../../02-Secure-Development/ControlCoverage/Feature/BotService.md - name: CDN href: ../../02-Secure-Development/ControlCoverage/Feature/CDN.md - name: Cloud Service href: ../../02-Secure-Development/ControlCoverage/Feature/CloudService.md + - name: Container Instances + href: ../../02-Secure-Development/ControlCoverage/Feature/ContainerInstances.md - name: Cosmos DB href: ../../02-Secure-Development/ControlCoverage/Feature/CosmosDB.md + - name: Databricks + href: ../../02-Secure-Development/ControlCoverage/Feature/Databricks.md - name: DataFactory href: ../../02-Secure-Development/ControlCoverage/Feature/DataFactory.md - name: DataLakeAnalytics @@ -48,6 +58,8 @@ href: ../../02-Secure-Development/ControlCoverage/Feature/ERvNet.md - name: EventHub href: ../../02-Secure-Development/ControlCoverage/Feature/EventHub.md + - name: HDInsight + href: ../../02-Secure-Development/ControlCoverage/Feature/HDInsight.md - name: KeyVault href: ../../02-Secure-Development/ControlCoverage/Feature/KeyVault.md - name: LoadBalancer @@ -86,11 +98,97 @@ href: ../../03-Security-In-CICD/Readme.md - name: Continous Assurance href: ../../04-Continous-Assurance/Readme.md + items: + - name: Script for preparing target subscription for CentralMode CA + href: ../../04-Continous-Assurance/scripts/PrepareTargetSubscriptionForCentralModeCA.md - name: Alerting and Monitoring href: ../../05-Alerting-and-Monitoring/Readme.md + items: + - name: OMS Queries + href: ../../05-Alerting-and-Monitoring/OMSQueries.md - name: Security Telemetry href: ../../06-Security-Telemetry/Readme.md + items: + - name: App Insight Queries + href: ../../06-Security-Telemetry/App-Insights-Queries/Readme.md - name: Customizing AzSK for your organization href: ../../07-Customizing-AzSK-for-your-Org/Readme.md -- name: Advanced features - href: ../../08-Advanced-Features/Readme.md + items: + - name: Extending AzSK Module + href: ../../07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/Readme.md + items: + - name: AppInsights.ext.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/AppInsights.ext.json + - name: AppInsights.ext.ps1 + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/AppInsights.ext.ps1 + - name: AppInsights.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/AppInsights.json + - name: AppInsights.ps1 + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/AppInsights.ps1 + - name: Feature.ext.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/Feature.ext.json + - name: Feature.ext.ps1 + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/Feature.ext.ps1 + - name: ListenerName.ext.ps1 + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/ListenerName.ext.ps1 + - name: SubscriptionCore.ext.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/SubscriptionCore.ext.json + - name: SubscriptionCore.ext.ps1 + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Extending%20AzSK%20Module/SubscriptionCore.ext.ps1 + items: + - name: Org Policy Health Check + href: ../../07-Customizing-AzSK-for-your-Org/OrgPolicyHealthCheck.md + - name: Org Policy Updates + href: ../../07-Customizing-AzSK-for-your-Org/OrgPolicyUpdate.md + - name: Scripts + href: ../../07-Customizing-AzSK-for-your-Org/Readme.md + items: + - name: OrgPolicyFixScript.ps1.txt + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.ps1.txt + - name: OrgPolicyFixScript.txt + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyFixScript.txt + - name: OrgPolicyHealthCheck.ps1.txt + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.ps1.txt + - name: OrgPolicyHealthCheck.txt + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyHealthCheck.txt + - name: OrgPolicyPushOrgMappingEvents.txt + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/Scripts/OrgPolicyPushOrgMappingEvents.txt + - name: Templates + href: ../../07-Customizing-AzSK-for-your-Org/Readme.md + items: + - name: AzSKComplianceReport.pbit + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/TemplateFiles/AzSKComplianceReport.pbit + - name: OrgMapping.csv + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMapping.csv + - name: OrgMappingDataSourceSchema.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/07-Customizing-AzSK-for-your-Org/TemplateFiles/OrgMappingDataSourceSchema.json +- name: Miscellaneous features + href: ../../08-Miscellaneous-Features/Readme.md +- name: Secure Azure DevOps (VSTS) -Preview + href: ../../09-AzureDevOps(VSTS)-Security/Readme.md +- name: Continuous-Assurance-for-in-Cluster + href: ../../10-Continuous-Assurance-for-in-Cluster/Readme.md +- name: ARM Templates + href: ../../ARMTemplates/Readme.md + items: + - name: AppService.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/AppService.json + - name: EventHub.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/EventHub.json + - name: KeyVault.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/KeyVault.json + - name: NotificationHub.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/NotificationHub.json + - name: ServiceBus.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/ServiceBus.json + - name: SQLDatabase.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/SQLDatabase.json + - name: StorageTemplate.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/StorageTemplate.json + - name: TrafficManager.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/TrafficManager.json + - name: VirtualMachine.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/VirtualMachine.json + - name: VirtualNetwork.json + href: https://github.com/azsk/DevOpsKit-docs/blob/master/ARMTemplates/VirtualNetwork.json + diff --git a/WebsiteContent/bread/toc.yml b/WebsiteContent/bread/toc.yml index 1f409a30..fbcc887f 100644 --- a/WebsiteContent/bread/toc.yml +++ b/WebsiteContent/bread/toc.yml @@ -24,6 +24,10 @@ topicHref: ../../02-Secure-Development/ControlCoverage/Feature/AnalysisServices.md - name: App Service topicHref: ../../02-Secure-Development/ControlCoverage/Feature/AppService.md + - name: Application Proxy + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/ApplicationProxy.md + - name: API Management + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/APIManagement.md - name: Automation topicHref: ../../02-Secure-Development/ControlCoverage/Feature/Automation.md - name: Batch @@ -32,6 +36,10 @@ topicHref: ../../02-Secure-Development/ControlCoverage/Feature/CDN.md - name: Cloud Service topicHref: ../../02-Secure-Development/ControlCoverage/Feature/CloudService.md + - name: Container Instances + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/ContainerInstances.md + - name: Container Registry + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/ContainerRegistry.md - name: Cosmos DB topicHref: ../../02-Secure-Development/ControlCoverage/Feature/CosmosDB.md - name: DataFactory @@ -44,8 +52,12 @@ topicHref: ../../02-Secure-Development/ControlCoverage/Feature/ERvNet.md - name: EventHub topicHref: ../../02-Secure-Development/ControlCoverage/Feature/EventHub.md + - name: HDInsight + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/HDInsight.md - name: KeyVault topicHref: ../../02-Secure-Development/ControlCoverage/Feature/KeyVault.md + - name: Kubernetes Service + topicHref: ../../02-Secure-Development/ControlCoverage/Feature/KubernetesService.md - name: LoadBalancer topicHref: ../../02-Secure-Development/ControlCoverage/Feature/LoadBalancer.md - name: LogicApps @@ -85,4 +97,4 @@ - name: Alerting and Monitoring topicHref: ../../05-Alerting-and-Monitoring/Readme.md - name: Security Telemetry - topicHref: ../../06-Security-Telemetry/Readme.md \ No newline at end of file + topicHref: ../../06-Security-Telemetry/Readme.md diff --git a/WebsiteContent/landingContent/bottomContent/DocumentationSection.md b/WebsiteContent/landingContent/bottomContent/DocumentationSection.md index a06a7783..9ff3fe7d 100644 --- a/WebsiteContent/landingContent/bottomContent/DocumentationSection.md +++ b/WebsiteContent/landingContent/bottomContent/DocumentationSection.md @@ -1 +1 @@ -The "Secure DevOps Kit for Azure" (will be referred to as 'AzSK' henceforth) is a collection of scripts, tools, extensions, automations, etc. that caters to the end to end Azure subscription and resource security needs for dev ops teams using extensive automation and smoothly integrating security into native dev ops workflows helping accomplish secure dev ops \ No newline at end of file +The "Secure DevOps Kit for Azure" (will be referred to as 'AzSK' henceforth) is a collection of scripts, tools, extensions, automations, etc. that caters to the end to end Azure subscription and resource security needs for dev ops teams using extensive automation and smoothly integrating security into native dev ops workflows helping accomplish secure dev ops diff --git a/WebsiteContent/toc.yml b/WebsiteContent/toc.yml index 9cefc723..6f177527 100644 --- a/WebsiteContent/toc.yml +++ b/WebsiteContent/toc.yml @@ -3,4 +3,4 @@ - name: Blog href: ../Blogs/ - name: Releases - href: ../Release/ \ No newline at end of file + href: ../ReleaseNotes/ diff --git a/docfx.json b/docfx.json index bc520aa2..b301b403 100644 --- a/docfx.json +++ b/docfx.json @@ -40,9 +40,9 @@ "apiSpecFolder": "DevOpsKit-docs" }, "_gitUrlPattern": "github", - "_appLogoPath": "Images/Icons/AzSDK_Logo.PNG", - "_appFooter": "Copyright (c) - Microsoft 2017. All rights reserved.", - "_appFaviconPath": "Images/Icons/AzSDK_Favicon.PNG" + "_appLogoPath": "Images/Icons/AzSK_Logo.PNG", + "_appFooter": "Copyright (c) - Microsoft 2019. All rights reserved.", + "_appFaviconPath": "Images/Icons/AzSK_Favicon.PNG" }, "globalMetadataFiles":[], "fileMetadataFiles": [], @@ -54,4 +54,4 @@ "keepFileLink": false, "cleanupCacheHistory": false } -} +} \ No newline at end of file