From a8ee9abcc745a9fb7aa4b30ef470fb7527089d5c Mon Sep 17 00:00:00 2001 From: batemansogq Date: Fri, 6 Oct 2023 06:42:28 +0000 Subject: [PATCH 01/22] initial ML updates --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 58 +++++++++++++++++++ .../rules/Azure.ML.Rule.yaml | 25 ++++++++ 2 files changed, 83 insertions(+) create mode 100644 docs/en/rules/Azure.ML.ComputeIdleShutdown.md diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md new file mode 100644 index 00000000000..48b6386dbc7 --- /dev/null +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -0,0 +1,58 @@ +--- +reviewed: 2023-10-06 +severity: Critical +pillar: Cost Optimization +category: Provision +resource: ML +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeIdleShutdown/ +--- + +# Name of rule + +## SYNOPSIS + +Use ML - Compute Instances configured for idle shutdown. + +## DESCRIPTION + +Machine Learning uses compute instances as a training or inference compute for development and testing. It's similar to a virtual machine on the cloud. + +To avoid getting charged for a compute instance that is switched on but inactive, you can configure when to shut down your compute instance due to inactivity. + + +## RECOMMENDATION + +Consider configuring ML - Compute Instances to automatically shutdown after a period of idle use as part of a broader cost optimization strategy. + +## EXAMPLES + +### Configure with Azure template + +To deploy resource that pass this rule: + +- steps + +For example: + +```json + +``` + +### Configure with Bicep + +To deploy resource that pass this rule: + +- steps + +For example: + +```bicep + +``` + +## LINKS + +- [Configure idle shutdown](https://learn.microsoft.com/azure/machine-learning/how-to-create-compute-instance?view=azureml-api-2&tabs=azure-cli#configure-idle-shutdown) +- [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#compute-objects) +- [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) +- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 530a03f7ec7..b43d19ded09 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -4,3 +4,28 @@ # # Validation rules for Azure Machine Learning # + +--- +# Synopsis: ML Compute Instances have idle shutdown enabled +apiVersion: github.com/microsoft/PSRule/v1 +kind: Rule +metadata: + name: Azure.ML.ComputeIdleShutdown + ref: AZR-000394 + tags: + release: GA + ruleSet: 2023_10 + Azure.WAF/pillar: Cost Optimization +spec: + type: + - Microsoft.MachineLearningServices/workspaces/computes + condition: + allOf: + - field: computeType + equals: 'ComputeInstance' + - field: properties.parameters.idleTimeBeforeShutdown + exists: true + - field: properties.parameters.idleTimeBeforeShutdown + isNumeric: true + +# Synopsis: ML Compute clusters should have local authentication methods disabled From b6ea20972e8d6dfc822999de53ed22b0b1fd8a0a Mon Sep 17 00:00:00 2001 From: batemansogq Date: Mon, 9 Oct 2023 03:10:16 +0000 Subject: [PATCH 02/22] initial AML changes --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 2 +- docs/examples-ML.bicep | 39 ++++++++++++++ .../rules/Azure.ML.Rule.yaml | 9 ++-- .../Azure.ML.Tests.ps1 | 51 ++++++++++++++++++- .../Resources.ML.json | 37 ++++++++++++++ 5 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 docs/examples-ML.bicep create mode 100644 tests/PSRule.Rules.Azure.Tests/Resources.ML.json diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index 48b6386dbc7..e0b4fcaf534 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -17,7 +17,7 @@ Use ML - Compute Instances configured for idle shutdown. Machine Learning uses compute instances as a training or inference compute for development and testing. It's similar to a virtual machine on the cloud. -To avoid getting charged for a compute instance that is switched on but inactive, you can configure when to shut down your compute instance due to inactivity. +To avoid getting charged for a compute instance that is switched on but not being actively used, you can configure when to automatically shut down compute instances due to inactivity. ## RECOMMENDATION diff --git a/docs/examples-ML.bicep b/docs/examples-ML.bicep new file mode 100644 index 00000000000..d46d457e776 --- /dev/null +++ b/docs/examples-ML.bicep @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Bicep documentation examples + +@description('The name of the ML - Compute Instance.') +param name string + +@description('The location resources will be deployed.') +param location string = resourceGroup().location + +@description('The VM SKU to be deployed.') +param vmSize string = 'STANDARD_D2_V2' + +@description('The Idle time before shutdown, as a string in ISO 8601 format.') +// this must be a string in ISO 8601 format +param idleTimeBeforeShutdown string = 'PT15M' + +resource managedRg 'Microsoft.Resources/resourceGroups@2022-09-01' existing = { + scope: subscription() + name: 'psrule' +} + +resource mlWorkspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' existing = { + name: 'example-ws' +} + +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ + name: '${mlWorkspace.name}/${name}' + location: location + properties:{ + managedResourceGroupId: managedRg.id + computeType: 'ComputeInstance' + properties: { + vmSize: vmSize + idleTimeBeforeShutdown: idleTimeBeforeShutdown + } + } +} diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index b43d19ded09..a4174a596fa 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -11,7 +11,7 @@ apiVersion: github.com/microsoft/PSRule/v1 kind: Rule metadata: name: Azure.ML.ComputeIdleShutdown - ref: AZR-000394 + ref: AZR-000403 tags: release: GA ruleSet: 2023_10 @@ -21,11 +21,10 @@ spec: - Microsoft.MachineLearningServices/workspaces/computes condition: allOf: - - field: computeType + - field: properties.parameters.computeType equals: 'ComputeInstance' - - field: properties.parameters.idleTimeBeforeShutdown + - field: properties.properties.parameters.idleTimeBeforeShutdown exists: true - - field: properties.parameters.idleTimeBeforeShutdown - isNumeric: true + # Synopsis: ML Compute clusters should have local authentication methods disabled diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index 4ee95f2b342..deb50c98671 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -2,5 +2,54 @@ # Licensed under the MIT License. # -# Unit tests for Azure Machine Learning rules +# Unit tests for Azure ML rules # + +[CmdletBinding()] +param () + +BeforeAll { + # Setup error handling + $ErrorActionPreference = 'Stop'; + Set-StrictMode -Version latest; + + if ($Env:SYSTEM_DEBUG -eq 'true') { + $VerbosePreference = 'Continue'; + } + + # Setup tests paths + $rootPath = $PWD; + Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Azure) -Force; + $here = (Resolve-Path $PSScriptRoot).Path; +} + +Describe 'Azure.ML' -Tag 'ML' { + Context 'Conditions' { + BeforeAll { + $invokeParams = @{ + Baseline = 'Azure.All' + Module = 'PSRule.Rules.Azure' + WarningAction = 'Ignore' + ErrorAction = 'Stop' + } + $dataPath = Join-Path -Path $here -ChildPath 'Resources.ML.json'; + $result = Invoke-PSRule @invokeParams -InputPath $dataPath; + } + + It 'Azure.ML.ComputeIdleShutdown' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.ComputeIdleShutdown' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'amlb'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'amla'; + } + } +} diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json new file mode 100644 index 00000000000..8b804578f9f --- /dev/null +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -0,0 +1,37 @@ +[ + { + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/amla", + "name": "test-ws/amla", + "location": "eastus", + "tags": { + "application": "ML" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", + "computeType": "ComputeInstance", + "properties": { + "vmSize": "STANDARD_D2_V2", + "idleTimeBeforeShutdown": "PT15M" + } + } + }, + { + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/amlb", + "name": "test-ws/amlb", + "location": "eastus", + "tags": { + "application": "ML" + }, + "properties": { + "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", + "computeType": "ComputeInstance", + "properties": { + "vmSize": "STANDARD_D2_V2" + } + } + } +] From 1f3ec9464fe91bef9fa5b80965467e34e3cb1d99 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Mon, 9 Oct 2023 10:41:04 +0000 Subject: [PATCH 03/22] corrected ML test --- src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml | 11 ++++------- tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 | 4 ++-- tests/PSRule.Rules.Azure.Tests/Resources.ML.json | 14 +++++++------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index a4174a596fa..613011136d4 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -15,16 +15,13 @@ metadata: tags: release: GA ruleSet: 2023_10 - Azure.WAF/pillar: Cost Optimization + Azure.WAF/pillar: 'Cost Optimization' spec: type: - Microsoft.MachineLearningServices/workspaces/computes condition: allOf: - - field: properties.parameters.computeType - equals: 'ComputeInstance' - - field: properties.properties.parameters.idleTimeBeforeShutdown + - field: properties.computeType + equals: ComputeInstance + - field: properties.properties.idleTimeBeforeShutdown exists: true - - -# Synopsis: ML Compute clusters should have local authentication methods disabled diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index deb50c98671..985b2ab3337 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -43,13 +43,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'amlb'; + $ruleResult.TargetName | Should -Be 'ml-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'amla'; + $ruleResult.TargetName | Should -Be 'ml-a'; } } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index 8b804578f9f..3d83f07d792 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -2,9 +2,9 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/amla", - "name": "test-ws/amla", - "location": "eastus", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-a", + "name": "ml-a", + "location": "westus", "tags": { "application": "ML" }, @@ -20,15 +20,15 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/amlb", - "name": "test-ws/amlb", - "location": "eastus", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-b", + "name": "ml-b", + "location": "westus", "tags": { "application": "ML" }, "properties": { "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", - "computeType": "ComputeInstance", + "computeType": "AML", "properties": { "vmSize": "STANDARD_D2_V2" } From 209591f3fa79667230b07ea1a88dd2ac00e8ebce Mon Sep 17 00:00:00 2001 From: batemansogq Date: Mon, 9 Oct 2023 10:43:59 +0000 Subject: [PATCH 04/22] corrected ML JSON, backing out test data --- tests/PSRule.Rules.Azure.Tests/Resources.ML.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index 3d83f07d792..d0d6734a3a6 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -28,7 +28,7 @@ }, "properties": { "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", - "computeType": "AML", + "computeType": "ComputeInstance", "properties": { "vmSize": "STANDARD_D2_V2" } From 227f1699c0bc4ff05f71c2c302ab33601d7925f4 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Mon, 9 Oct 2023 11:07:45 +0000 Subject: [PATCH 05/22] finalised md doco for ML --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index e0b4fcaf534..573586d4499 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -28,31 +28,57 @@ Consider configuring ML - Compute Instances to automatically shutdown after a pe ### Configure with Azure template -To deploy resource that pass this rule: +To deploy an ML - compute instance that pass this rule: -- steps +- Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = "PT15M" +- Define the "idleTimeBeforeShutdown" as this value For example: ```json - +{ + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'example-mg')]", + "computeType": "ComputeInstance", + "properties": { + "vmSize": "[parameters('vmSize')]", + "idleTimeBeforeShutdown": "[parameters('idleTimeBeforeShutdown')]" + } + } +} ``` ### Configure with Bicep -To deploy resource that pass this rule: +To deploy an ML - compute instance that pass this rule: -- steps +- Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = 'PT15M' +- Define the "idleTimeBeforeShutdown" as this value For example: ```bicep - -``` +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ + name: '${mlWorkspace.name}/${name}' + location: location + properties:{ + managedResourceGroupId: managedRg.id + computeType: 'ComputeInstance' + properties: { + vmSize: vmSize + idleTimeBeforeShutdown: idleTimeBeforeShutdown // this must be a string in ISO 8601 format + } + } +} ## LINKS - [Configure idle shutdown](https://learn.microsoft.com/azure/machine-learning/how-to-create-compute-instance?view=azureml-api-2&tabs=azure-cli#configure-idle-shutdown) - [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#compute-objects) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) - [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) From c905e4d975618c3178ba2a12260c91a05c036a39 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Mon, 9 Oct 2023 23:27:48 +0000 Subject: [PATCH 06/22] inital ML disable local rule --- docs/en/rules/Azure.ML.DisableLocalAuth.md | 56 +++++++++++++++++++ .../rules/Azure.ML.Rule.yaml | 17 ++++++ .../Azure.ML.Tests.ps1 | 16 ++++++ .../Resources.ML.json | 1 + 4 files changed, 90 insertions(+) create mode 100644 docs/en/rules/Azure.ML.DisableLocalAuth.md diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md new file mode 100644 index 00000000000..735af5028db --- /dev/null +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -0,0 +1,56 @@ +--- +reviewed: 2023-10-10 +severity: Critical +pillar: Security +category: Provision +resource: ML +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.DisableLocalAuth/ +--- + +# Name of rule + +## SYNOPSIS + +Azure Machine Learning compute resources should have local authentication methods disabled. + +## DESCRIPTION + +Controls whether an Azure Machine Learning compute cluster or instance should disable local authentication (SSH). + +## RECOMMENDATION + +ML - Compute should be configured with local authentication disabled as part of a broader security strategy. + +## EXAMPLES + +### Configure with Azure template + +To deploy resource that pass this rule: + +- steps + +For example: + +```json + +``` + +### Configure with Bicep + +To deploy resource that pass this rule: + +- steps + +For example: + +```bicep + +``` + +## LINKS + +- [Disable local authentication](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-integrate-azure-policy?view=azureml-api-2#disable-local-authentication) +- [ML - Compute objects](https://learn.microsoft.com/en-gb/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) +- [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) +- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 613011136d4..01d72b1bf54 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -25,3 +25,20 @@ spec: equals: ComputeInstance - field: properties.properties.idleTimeBeforeShutdown exists: true + +# Synopsis: ML Compute has local authentication disabled +apiVersion: github.com/microsoft/PSRule/v1 +kind: Rule +metadata: + name: Azure.ML.DisableLocalAuth + ref: AZR-000404 + tags: + release: GA + ruleSet: 2023_10 + Azure.WAF/pillar: Security +spec: + type: + - Microsoft.MachineLearningServices/workspaces/computes + condition: + field: properties.properties.disableLocalAuth.value + equals: true diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index 985b2ab3337..5623aa64dda 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -51,5 +51,21 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult.Length | Should -Be 1; $ruleResult.TargetName | Should -Be 'ml-a'; } + + It 'Azure.ML.DisableLocalAuth' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.DisableLocalAuth' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-b'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-a'; + } } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index d0d6734a3a6..99154a57ce5 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -11,6 +11,7 @@ "properties": { "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", "computeType": "ComputeInstance", + "disableLocalAuth": True, "properties": { "vmSize": "STANDARD_D2_V2", "idleTimeBeforeShutdown": "PT15M" From 5061fae9fe7111440a753b009adc2ba7b8a1a36d Mon Sep 17 00:00:00 2001 From: batemansogq Date: Tue, 10 Oct 2023 05:10:38 +0000 Subject: [PATCH 07/22] ML disable admin rule --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 4 +- docs/en/rules/Azure.ML.DisableLocalAuth.md | 37 ++++++++++++++++--- .../rules/Azure.ML.Rule.yaml | 4 +- .../Resources.ML.json | 2 +- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index 573586d4499..4f95c571dc6 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -28,7 +28,7 @@ Consider configuring ML - Compute Instances to automatically shutdown after a pe ### Configure with Azure template -To deploy an ML - compute instance that pass this rule: +To deploy an ML - compute instance that complies with this rule: - Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = "PT15M" - Define the "idleTimeBeforeShutdown" as this value @@ -54,7 +54,7 @@ For example: ### Configure with Bicep -To deploy an ML - compute instance that pass this rule: +To deploy an ML - compute instance that complies with this rule: - Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = 'PT15M' - Define the "idleTimeBeforeShutdown" as this value diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index 735af5028db..349f5f45f15 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -25,27 +25,54 @@ ML - Compute should be configured with local authentication disabled as part of ### Configure with Azure template -To deploy resource that pass this rule: +To deploy an ML - compute that complies with this rule: -- steps +- Set the `disableLocalAuth` property value to true. For example: ```json +{ + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'psrule')]", + "computeType": "[parameters('computeType')]", + "disableLocalAuth": true, + "properties": { + "vmSize": "[parameters('vmSize')]", + } + } +} + ``` ### Configure with Bicep -To deploy resource that pass this rule: +To deploy an ML - compute that complies with this rule: -- steps +- Set the `disableLocalAuth` property value to `true`. For example: ```bicep -``` +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ + name: '${mlWorkspace.name}/${name}' + location: location + + properties:{ + managedResourceGroupId: managedRg.id + computeType: ComputeType + disableLocalAuth: true + properties: { + vmSize: vmSize + } + } +} ## LINKS diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 01d72b1bf54..149dc71c090 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -25,7 +25,7 @@ spec: equals: ComputeInstance - field: properties.properties.idleTimeBeforeShutdown exists: true - +--- # Synopsis: ML Compute has local authentication disabled apiVersion: github.com/microsoft/PSRule/v1 kind: Rule @@ -40,5 +40,5 @@ spec: type: - Microsoft.MachineLearningServices/workspaces/computes condition: - field: properties.properties.disableLocalAuth.value + field: properties.disableLocalAuth equals: true diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index 99154a57ce5..a1b5caf3bb0 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -11,7 +11,7 @@ "properties": { "managedResourceGroupId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg", "computeType": "ComputeInstance", - "disableLocalAuth": True, + "disableLocalAuth": true, "properties": { "vmSize": "STANDARD_D2_V2", "idleTimeBeforeShutdown": "PT15M" From 63a0d9ca73f3710459d20e48f05681a100da82e5 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Tue, 10 Oct 2023 11:08:27 +0000 Subject: [PATCH 08/22] ML compute vnet added, md update on hyperlinks --- docs/en/rules/Azure.ML.ComputeVnet.md | 90 +++++++++++++++++++ docs/en/rules/Azure.ML.DisableLocalAuth.md | 11 +-- .../rules/Azure.ML.Rule.yaml | 18 ++++ .../Azure.ML.Tests.ps1 | 16 ++++ .../Resources.ML.json | 5 +- 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 docs/en/rules/Azure.ML.ComputeVnet.md diff --git a/docs/en/rules/Azure.ML.ComputeVnet.md b/docs/en/rules/Azure.ML.ComputeVnet.md new file mode 100644 index 00000000000..41cb037b1df --- /dev/null +++ b/docs/en/rules/Azure.ML.ComputeVnet.md @@ -0,0 +1,90 @@ +--- +reviewed: 2023-10-10 +severity: Critical +pillar: Security +category: Networking +resource: ML +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeVnet/ +--- + +# Name of rule + +## SYNOPSIS + +Azure Machine Learning Computes should be hosted in a virtual network (VNet). + +## DESCRIPTION + +Azure Virtual Networks (VNets) provide enhanced security and isolation for your Azure Machine Learning Compute Clusters and Instances, as well as subnets, access control policies, and other features to further restrict access. When a compute is configured with a virtual network, it is not publicly addressable and can only be accessed from virtual machines and applications within the virtual network. + +## RECOMMENDATION + +ML - Compute should be hosted in a virtual network (VNet) as part of a broader security strategy. + +## EXAMPLES + +### Configure with Azure template + +To deploy an ML - compute that complies with this rule: + +- update the compute properties to reference a specific subnet. + +For example: + +```json + +{ + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'example-rg')]", + "computeType": "[parameters('computeType')]", + "properties": { + "vmSize": "[parameters('vmSize')]", + "subnet": { + "id": "[parameters('subnetId')]" + } + } + } +} + +``` + +### Configure with Bicep + +To deploy an ML - compute that complies with this rule: + +- update the compute properties to reference a specific subnet. + +For example: + +```bicep + +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ + name: '${mlWorkspace.name}/${name}' + location: location + + properties:{ + managedResourceGroupId: managedRg.id + computeType: ComputeType + properties: { + vmSize: vmSize + subnet:{ + id: subnet.id + } + } + } +} +``` + + +## LINKS + +- [Managed compute in a managed virtual network](https://learn.microsoft.com/azure/machine-learning/how-to-managed-network-compute?view=azureml-api-2&tabs=azure-cli) +- [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) +- [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) +- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) + diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index 349f5f45f15..5dd6578796e 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -2,7 +2,7 @@ reviewed: 2023-10-10 severity: Critical pillar: Security -category: Provision +category: Identity and Access Management resource: ML online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.DisableLocalAuth/ --- @@ -15,7 +15,7 @@ Azure Machine Learning compute resources should have local authentication method ## DESCRIPTION -Controls whether an Azure Machine Learning compute cluster or instance should disable local authentication (SSH). +Azure Machine Learning compute resources should have local authentication (SSH) methods disabled. ## RECOMMENDATION @@ -39,7 +39,7 @@ For example: "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", "location": "[parameters('location')]", "properties": { - "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'psrule')]", + "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'example-rg')]", "computeType": "[parameters('computeType')]", "disableLocalAuth": true, "properties": { @@ -73,11 +73,12 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp } } } +``` ## LINKS -- [Disable local authentication](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-integrate-azure-policy?view=azureml-api-2#disable-local-authentication) -- [ML - Compute objects](https://learn.microsoft.com/en-gb/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) +- [Disable local authentication](https://learn.microsoft.com/azure/machine-learning/how-to-integrate-azure-policy?view=azureml-api-2#disable-local-authentication) +- [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) - [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 149dc71c090..dd5980a2731 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -42,3 +42,21 @@ spec: condition: field: properties.disableLocalAuth equals: true + +--- +# Synopsis: ML Compute should be in a virtual network +apiVersion: github.com/microsoft/PSRule/v1 +kind: Rule +metadata: + name: Azure.ML.ComputeVnet + ref: AZR-000405 + tags: + release: GA + ruleSet: 2023_10 + Azure.WAF/pillar: Security +spec: + type: + - Microsoft.MachineLearningServices/workspaces/computes + condition: + field: properties.properties.subnet + exists: true diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index 5623aa64dda..fda7f3f0228 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -67,5 +67,21 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult.Length | Should -Be 1; $ruleResult.TargetName | Should -Be 'ml-a'; } + + It 'Azure.ML.ComputeVnet' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.ComputeVnet' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-b'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-a'; + } } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index a1b5caf3bb0..d9bb6be199c 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -14,7 +14,10 @@ "disableLocalAuth": true, "properties": { "vmSize": "STANDARD_D2_V2", - "idleTimeBeforeShutdown": "PT15M" + "idleTimeBeforeShutdown": "PT15M", + "subnet":{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/test-sub" + } } } }, From 02096ac60e46273edcb1936e3003f033f369ede9 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 11 Oct 2023 03:07:24 +0000 Subject: [PATCH 09/22] links updated for ML rules --- docs/en/rules/Azure.ML.ComputeVnet.md | 2 +- docs/en/rules/Azure.ML.DisableLocalAuth.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeVnet.md b/docs/en/rules/Azure.ML.ComputeVnet.md index 41cb037b1df..79ad14ed78a 100644 --- a/docs/en/rules/Azure.ML.ComputeVnet.md +++ b/docs/en/rules/Azure.ML.ComputeVnet.md @@ -86,5 +86,5 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp - [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) -- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index 5dd6578796e..f21d835bebb 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -15,7 +15,7 @@ Azure Machine Learning compute resources should have local authentication method ## DESCRIPTION -Azure Machine Learning compute resources should have local authentication (SSH) methods disabled. +Disabling local authentication methods improves security by ensuring that Machine Learning Computes require Azure Active Directory identities exclusively for authentication. Learn more at: https://aka.ms/azure-ml-aad-policy. ## RECOMMENDATION @@ -81,4 +81,5 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp - [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) -- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) +- [Azure Policy Regulatory Compliance controls for Azure Machine Learning](https://learn.microsoft.com/azure/machine-learning/security-controls-policy?view=azureml-api-2) +- [WAF - Authentication with Azure AD](https://learn.microsoft.com/azure/well-architected/security/design-identity-authentication) From 748d00a5e25bc4f0a96761cbae727c0b35053574 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 11 Oct 2023 23:33:28 +0000 Subject: [PATCH 10/22] update ML compute test ref for extend to workspaces --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 1 - tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 | 12 ++++++------ tests/PSRule.Rules.Azure.Tests/Resources.ML.json | 8 ++++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index 4f95c571dc6..43d38e75225 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -19,7 +19,6 @@ Machine Learning uses compute instances as a training or inference compute for d To avoid getting charged for a compute instance that is switched on but not being actively used, you can configure when to automatically shut down compute instances due to inactivity. - ## RECOMMENDATION Consider configuring ML - Compute Instances to automatically shutdown after a period of idle use as part of a broader cost optimization strategy. diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index fda7f3f0228..7de419019ee 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -43,13 +43,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-b'; + $ruleResult.TargetName | Should -Be 'ml-comp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-a'; + $ruleResult.TargetName | Should -Be 'ml-comp-a'; } It 'Azure.ML.DisableLocalAuth' { @@ -59,13 +59,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-b'; + $ruleResult.TargetName | Should -Be 'ml-comp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-a'; + $ruleResult.TargetName | Should -Be 'ml-comp-a'; } It 'Azure.ML.ComputeVnet' { @@ -75,13 +75,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-b'; + $ruleResult.TargetName | Should -Be 'ml-comp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-a'; + $ruleResult.TargetName | Should -Be 'ml-comp-a'; } } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index d9bb6be199c..a5dcf378b5b 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -2,8 +2,8 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-a", - "name": "ml-a", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-comp-a", + "name": "ml-comp-a", "location": "westus", "tags": { "application": "ML" @@ -24,8 +24,8 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-b", - "name": "ml-b", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-comp-b", + "name": "ml-comp-b", "location": "westus", "tags": { "application": "ML" From c29ba4c9f0767308a4cee9ef09f058f719bb05ad Mon Sep 17 00:00:00 2001 From: batemansogq Date: Thu, 12 Oct 2023 05:53:38 +0000 Subject: [PATCH 11/22] ML Workspace rule added, ML titles added to mds --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 2 +- docs/en/rules/Azure.ML.ComputeVnet.md | 3 +- docs/en/rules/Azure.ML.DisableLocalAuth.md | 2 +- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 94 +++++++++++++++++++ .../rules/Azure.ML.Rule.yaml | 21 +++++ .../Azure.ML.Tests.ps1 | 29 ++++-- .../Resources.ML.json | 49 +++++++++- 7 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 docs/en/rules/Azure.ML.WrkspPublicAccess.md diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index 43d38e75225..9988ec1dd52 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -7,7 +7,7 @@ resource: ML online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeIdleShutdown/ --- -# Name of rule +# ML Compute Idle Shutdown ## SYNOPSIS diff --git a/docs/en/rules/Azure.ML.ComputeVnet.md b/docs/en/rules/Azure.ML.ComputeVnet.md index 79ad14ed78a..30792925c17 100644 --- a/docs/en/rules/Azure.ML.ComputeVnet.md +++ b/docs/en/rules/Azure.ML.ComputeVnet.md @@ -7,7 +7,7 @@ resource: ML online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeVnet/ --- -# Name of rule +# ML Compute hosted in VNet ## SYNOPSIS @@ -83,6 +83,7 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp ## LINKS - [Managed compute in a managed virtual network](https://learn.microsoft.com/azure/machine-learning/how-to-managed-network-compute?view=azureml-api-2&tabs=azure-cli) +- [ML - Network security and isolation](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2#network-security-and-isolation) - [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index f21d835bebb..5c90f44caf6 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -7,7 +7,7 @@ resource: ML online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.DisableLocalAuth/ --- -# Name of rule +# ML Compute has local authentication disabled ## SYNOPSIS diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md new file mode 100644 index 00000000000..d77c219f76b --- /dev/null +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -0,0 +1,94 @@ +--- +reviewed: 2023-10-12 +severity: Critical +pillar: Security +category: Networking +resource: ML +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.WrkspPublicAccess/ +--- + +# ML Workspace has public access disabled + +## SYNOPSIS + +Disable public network access from a ML - Workspace when behind VNet. + +## DESCRIPTION + +Disable public network access from a ML - Workspace when behind VNet. + +## RECOMMENDATION + +Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. + +## EXAMPLES + +### Configure with Azure template + +To deploy an ML - Workspace that complies with this rule: + +- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. + +For example: + +```json +{ + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "sku": { + "name": "basic", + "tier": "basic" + }, + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('name')]", + "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", + "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", + "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", + "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", + "allowPublicAccessWhenBehindVnet": false + } + +``` + +### Configure with Bicep + +To deploy an ML - Workspace that complies with this rule: + +- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. + +For example: + +```bicep +resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' = { + name: name + location: location + sku: { + name: 'basic' + tier: 'basic' + } + identity: { + type: 'SystemAssigned' + } + properties: { + friendlyName: friendlyName + keyVault: KeyVault.id + storageAccount: StorageAccount.id + applicationInsights: AppInsights.id + containerRegistry: ContainerRegistry.id + allowPublicAccessWhenBehindVnet: false + } +} + +``` + +## LINKS +- [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) +- [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index dd5980a2731..111b9eb7111 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -60,3 +60,24 @@ spec: condition: field: properties.properties.subnet exists: true + +--- +# Synopsis: Disable public network access from a ML Workspace when behind vnet +apiVersion: github.com/microsoft/PSRule/v1 +kind: Rule +metadata: + name: Azure.ML.WrkspPublicAccess + ref: AZR-000406 + tags: + release: GA + ruleSet: 2023_10 + Azure.WAF/pillar: Security +spec: + type: + - Microsoft.MachineLearningServices/workspaces + condition: + allOf: + - field: properties.allowPublicAccessWhenBehindVnet + exists: true + - field: properties.allowPublicAccessWhenBehindVnet + equals: false diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index 7de419019ee..40738e81ddc 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -43,13 +43,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-b'; + $ruleResult.TargetName | Should -Be 'mlcomp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-a'; + $ruleResult.TargetName | Should -Be 'mlcomp-a'; } It 'Azure.ML.DisableLocalAuth' { @@ -59,13 +59,13 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-b'; + $ruleResult.TargetName | Should -Be 'mlcomp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-a'; + $ruleResult.TargetName | Should -Be 'mlcomp-a'; } It 'Azure.ML.ComputeVnet' { @@ -75,13 +75,30 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-b'; + $ruleResult.TargetName | Should -Be 'mlcomp-b'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'ml-comp-a'; + $ruleResult.TargetName | Should -Be 'mlcomp-a'; } + + It 'Azure.ML.WrkspPublicAccess' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.WrkspPublicAccess' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-wks-b'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-wks-a'; + } + } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index a5dcf378b5b..40392b6abc4 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -2,8 +2,8 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-comp-a", - "name": "ml-comp-a", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/mlcomp-a", + "name": "mlcomp-a", "location": "westus", "tags": { "application": "ML" @@ -24,8 +24,8 @@ { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", - "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/ml-comp-b", - "name": "ml-comp-b", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.MachineLearningServices/workspaces/test-ws/computes/mlcomp-b", + "name": "mlcomp-b", "location": "westus", "tags": { "application": "ML" @@ -37,5 +37,46 @@ "vmSize": "STANDARD_D2_V2" } } + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "ml-wks-a", + "location": "westus", + "tags": { + "application": "ML" + }, + "sku": { + "name": "Basic", + "tier": "Basic" + }, + "kind": "Default", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "WorkspaceFriendlyName", + "allowPublicAccessWhenBehindVnet": false + } + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "ml-wks-b", + "location": "westus", + "tags": { + "application": "ML" + }, + "sku": { + "name": "Basic", + "tier": "Basic" + }, + "kind": "Default", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "WorkspaceFriendlyName" + } } ] From 610968d251d07e95f2b4bba71d5fc5be1016eee3 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Thu, 12 Oct 2023 05:55:24 +0000 Subject: [PATCH 12/22] text upds --- docs/en/rules/Azure.ML.DisableLocalAuth.md | 2 +- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index 5c90f44caf6..f2e1da8cb1d 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -15,7 +15,7 @@ Azure Machine Learning compute resources should have local authentication method ## DESCRIPTION -Disabling local authentication methods improves security by ensuring that Machine Learning Computes require Azure Active Directory identities exclusively for authentication. Learn more at: https://aka.ms/azure-ml-aad-policy. +Disabling local authentication methods improves security by ensuring that Machine Learning Computes require Azure Active Directory identities exclusively for authentication. ## RECOMMENDATION diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index d77c219f76b..6bafd0e488a 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -19,7 +19,7 @@ Disable public network access from a ML - Workspace when behind VNet. ## RECOMMENDATION -Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. +Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false, as part of a broader security strategy. ## EXAMPLES From d87d679ea971ca1425b3faa775be24244b6e952f Mon Sep 17 00:00:00 2001 From: batemansogq Date: Thu, 12 Oct 2023 06:23:20 +0000 Subject: [PATCH 13/22] ML Wks pub access rule added. Refs updated --- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 9 +- docs/en/rules/Azure.ML.WrkspVnetPubAccess.md | 94 +++++++++++++++++++ .../rules/Azure.ML.Rule.yaml | 20 +++- .../Azure.ML.Tests.ps1 | 16 ++++ .../Resources.ML.json | 6 +- 5 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 docs/en/rules/Azure.ML.WrkspVnetPubAccess.md diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index 6bafd0e488a..f58cc7aa587 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -11,15 +11,15 @@ online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.Wrk ## SYNOPSIS -Disable public network access from a ML - Workspace when behind VNet. +Disable public network access from a ML - Workspace. ## DESCRIPTION -Disable public network access from a ML - Workspace when behind VNet. +Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. You can control exposure of your workspaces by creating private endpoints instead. Learn more at: https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=azure-portal.. ## RECOMMENDATION -Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false, as part of a broader security strategy. +Consider setting the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled", as part of a broader security strategy. ## EXAMPLES @@ -87,6 +87,9 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' ``` ## LINKS + +- [Configure a private endpoint for an Azure Machine Learning workspace](https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=cli) + - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) diff --git a/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md new file mode 100644 index 00000000000..39e561302ad --- /dev/null +++ b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md @@ -0,0 +1,94 @@ +--- +reviewed: 2023-10-12 +severity: Critical +pillar: Security +category: Networking +resource: ML +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.WrkspVnetPubAccess/ +--- + +# ML Workspace has public access disabled behind a VNet + +## SYNOPSIS + +Disable public network access from a ML - Workspace when behind a VNet. + +## DESCRIPTION + +Disable public network access from a ML - Workspace when behind a VNet. + +## RECOMMENDATION + +Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false, as part of a broader security strategy. + +## EXAMPLES + +### Configure with Azure template + +To deploy an ML - Workspace that complies with this rule: + +- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. + +For example: + +```json +{ + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "sku": { + "name": "basic", + "tier": "basic" + }, + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('name')]", + "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", + "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", + "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", + "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", + "allowPublicAccessWhenBehindVnet": false + } + +``` + +### Configure with Bicep + +To deploy an ML - Workspace that complies with this rule: + +- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. + +For example: + +```bicep +resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' = { + name: name + location: location + sku: { + name: 'basic' + tier: 'basic' + } + identity: { + type: 'SystemAssigned' + } + properties: { + friendlyName: friendlyName + keyVault: KeyVault.id + storageAccount: StorageAccount.id + applicationInsights: AppInsights.id + containerRegistry: ContainerRegistry.id + allowPublicAccessWhenBehindVnet: false + } +} + +``` + +## LINKS +- [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) +- [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) +- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 111b9eb7111..affa91cb5f1 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -66,7 +66,7 @@ spec: apiVersion: github.com/microsoft/PSRule/v1 kind: Rule metadata: - name: Azure.ML.WrkspPublicAccess + name: Azure.ML.WrkspVnetPubAccess ref: AZR-000406 tags: release: GA @@ -81,3 +81,21 @@ spec: exists: true - field: properties.allowPublicAccessWhenBehindVnet equals: false + +--- +# Synopsis: Disable public network access from a ML Workspace +apiVersion: github.com/microsoft/PSRule/v1 +kind: Rule +metadata: + name: Azure.ML.WrkspPublicAccess + ref: AZR-000407 + tags: + release: GA + ruleSet: 2023_10 + Azure.WAF/pillar: Security +spec: + type: + - Microsoft.MachineLearningServices/workspaces + condition: + field: properties.publicNetworkAccess + equals: "Disabled" diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 index 40738e81ddc..cc1ef97cb3b 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ML.Tests.ps1 @@ -84,6 +84,22 @@ Describe 'Azure.ML' -Tag 'ML' { $ruleResult.TargetName | Should -Be 'mlcomp-a'; } + It 'Azure.ML.WrkspVnetPubAccess' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.WrkspVnetPubAccess' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-wks-b'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 1; + $ruleResult.TargetName | Should -Be 'ml-wks-a'; + } + It 'Azure.ML.WrkspPublicAccess' { $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ML.WrkspPublicAccess' }; diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json index 40392b6abc4..dc0e7853c14 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ML.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ML.json @@ -56,7 +56,8 @@ }, "properties": { "friendlyName": "WorkspaceFriendlyName", - "allowPublicAccessWhenBehindVnet": false + "allowPublicAccessWhenBehindVnet": false, + "publicNetworkAccess": "Disabled" } }, { @@ -76,7 +77,8 @@ "type": "SystemAssigned" }, "properties": { - "friendlyName": "WorkspaceFriendlyName" + "friendlyName": "WorkspaceFriendlyName", + "publicNetworkAccess": "Enabled" } } ] From bb864e4d16c47bedd7cc4868f71656286586f09b Mon Sep 17 00:00:00 2001 From: batemansogq Date: Thu, 12 Oct 2023 06:27:07 +0000 Subject: [PATCH 14/22] ML Wkspace md updated --- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 12 +++++------- docs/en/rules/Azure.ML.WrkspVnetPubAccess.md | 1 - 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index f58cc7aa587..e33b4715ced 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -15,7 +15,7 @@ Disable public network access from a ML - Workspace. ## DESCRIPTION -Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. You can control exposure of your workspaces by creating private endpoints instead. Learn more at: https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=azure-portal.. +Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. You can control exposure of your workspaces by creating private endpoints instead. ## RECOMMENDATION @@ -27,7 +27,7 @@ Consider setting the 'publicNetworkAccess' parameter of the Workspace properties To deploy an ML - Workspace that complies with this rule: -- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. +- update the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled". For example: @@ -50,7 +50,7 @@ For example: "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", - "allowPublicAccessWhenBehindVnet": false + "publicNetworkAccess": "Disabled" } ``` @@ -59,7 +59,7 @@ For example: To deploy an ML - Workspace that complies with this rule: -- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. +- update the 'publicNetworkAccess' parameter of the Workspace properties to 'Disabled'. For example: @@ -80,7 +80,7 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' storageAccount: StorageAccount.id applicationInsights: AppInsights.id containerRegistry: ContainerRegistry.id - allowPublicAccessWhenBehindVnet: false + publicNetworkAccess: 'Disabled' } } @@ -89,9 +89,7 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' ## LINKS - [Configure a private endpoint for an Azure Machine Learning workspace](https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=cli) - - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) -- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md index 39e561302ad..34c8a96930f 100644 --- a/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md +++ b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md @@ -90,5 +90,4 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) -- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) From d80b59168308f9417751deaba4b2f95a081ca3b6 Mon Sep 17 00:00:00 2001 From: Bernie White Date: Sun, 15 Oct 2023 13:56:05 +0000 Subject: [PATCH 15/22] Minor updates and tweaks --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 19 +++--- docs/en/rules/Azure.ML.ComputeVnet.md | 20 +++--- docs/en/rules/Azure.ML.DisableLocalAuth.md | 30 +++++---- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 62 +++++++++---------- docs/en/rules/Azure.ML.WrkspVnetPubAccess.md | 58 ++++++++--------- docs/examples-ML.bicep | 8 +-- 6 files changed, 96 insertions(+), 101 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index 9988ec1dd52..ac41f68cba0 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -3,7 +3,7 @@ reviewed: 2023-10-06 severity: Critical pillar: Cost Optimization category: Provision -resource: ML +resource: Machine Learning online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeIdleShutdown/ --- @@ -27,10 +27,10 @@ Consider configuring ML - Compute Instances to automatically shutdown after a pe ### Configure with Azure template -To deploy an ML - compute instance that complies with this rule: +To deploy an ML - compute instance that passes this rule: -- Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = "PT15M" -- Define the "idleTimeBeforeShutdown" as this value +- Set the `properties.properties.idleTimeBeforeShutdown` property with a ISO 8601 formatted string. + i.e. For an idle shutdown time of 15 minutes use `PT15M`. For example: @@ -53,15 +53,15 @@ For example: ### Configure with Bicep -To deploy an ML - compute instance that complies with this rule: +To deploy an ML - compute instance that passes this rule: -- Provide a idle shutdown time as an ISO 8601 format string, i.e. 15mins = 'PT15M' -- Define the "idleTimeBeforeShutdown" as this value +- Set the `properties.properties.idleTimeBeforeShutdown` property with a ISO 8601 formatted string. + i.e. For an idle shutdown time of 15 minutes use `PT15M`. For example: ```bicep -resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' = { name: '${mlWorkspace.name}/${name}' location: location properties:{ @@ -73,11 +73,12 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp } } } +``` ## LINKS +- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) - [Configure idle shutdown](https://learn.microsoft.com/azure/machine-learning/how-to-create-compute-instance?view=azureml-api-2&tabs=azure-cli#configure-idle-shutdown) - [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#compute-objects) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) -- [AI + Machine Learning cost estimates](https://learn.microsoft.com/azure/well-architected/cost/provision-ai-ml) diff --git a/docs/en/rules/Azure.ML.ComputeVnet.md b/docs/en/rules/Azure.ML.ComputeVnet.md index 30792925c17..271186e06de 100644 --- a/docs/en/rules/Azure.ML.ComputeVnet.md +++ b/docs/en/rules/Azure.ML.ComputeVnet.md @@ -2,8 +2,8 @@ reviewed: 2023-10-10 severity: Critical pillar: Security -category: Networking -resource: ML +category: Connectivity +resource: Machine Learning online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.ComputeVnet/ --- @@ -15,7 +15,8 @@ Azure Machine Learning Computes should be hosted in a virtual network (VNet). ## DESCRIPTION -Azure Virtual Networks (VNets) provide enhanced security and isolation for your Azure Machine Learning Compute Clusters and Instances, as well as subnets, access control policies, and other features to further restrict access. When a compute is configured with a virtual network, it is not publicly addressable and can only be accessed from virtual machines and applications within the virtual network. +Azure Virtual Networks (VNets) provide enhanced security and isolation for your Azure Machine Learning Compute Clusters and Instances, as well as subnets, access control policies, and other features to further restrict access. +When a compute is configured with a virtual network, it is not publicly addressable and can only be accessed from virtual machines and applications within the virtual network. ## RECOMMENDATION @@ -25,14 +26,13 @@ ML - Compute should be hosted in a virtual network (VNet) as part of a broader s ### Configure with Azure template -To deploy an ML - compute that complies with this rule: +To deploy an ML - compute that passes this rule: -- update the compute properties to reference a specific subnet. +- Set the `properties.disableLocalAuth` property to `true`. For example: ```json - { "type": "Microsoft.MachineLearningServices/workspaces/computes", "apiVersion": "2023-04-01", @@ -49,19 +49,17 @@ For example: } } } - ``` ### Configure with Bicep -To deploy an ML - compute that complies with this rule: +To deploy an ML - compute that passes this rule: -- update the compute properties to reference a specific subnet. +- Set the `properties.disableLocalAuth` property to `true`. For example: ```bicep - resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ name: '${mlWorkspace.name}/${name}' location: location @@ -79,7 +77,6 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp } ``` - ## LINKS - [Managed compute in a managed virtual network](https://learn.microsoft.com/azure/machine-learning/how-to-managed-network-compute?view=azureml-api-2&tabs=azure-cli) @@ -88,4 +85,3 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) - [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) - diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index f2e1da8cb1d..b559c012126 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -15,11 +15,11 @@ Azure Machine Learning compute resources should have local authentication method ## DESCRIPTION -Disabling local authentication methods improves security by ensuring that Machine Learning Computes require Azure Active Directory identities exclusively for authentication. +Disabling local authentication methods improves security by ensuring that Machine Learning Computes require Azure Active Directory identities exclusively for authentication. ## RECOMMENDATION -ML - Compute should be configured with local authentication disabled as part of a broader security strategy. +ML - Compute should be configured with local authentication disabled as part of a broader security strategy. ## EXAMPLES @@ -27,34 +27,32 @@ ML - Compute should be configured with local authentication disabled as part of To deploy an ML - compute that complies with this rule: -- Set the `disableLocalAuth` property value to true. +- Set the `properties.disableLocalAuth` property to `true`. For example: ```json - { - "type": "Microsoft.MachineLearningServices/workspaces/computes", - "apiVersion": "2023-04-01", - "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", - "location": "[parameters('location')]", + "type": "Microsoft.MachineLearningServices/workspaces/computes", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', 'example-ws', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'example-rg')]", + "computeType": "[parameters('computeType')]", + "disableLocalAuth": true, "properties": { - "managedResourceGroupId": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', 'example-rg')]", - "computeType": "[parameters('computeType')]", - "disableLocalAuth": true, - "properties": { - "vmSize": "[parameters('vmSize')]", - } + "vmSize": "[parameters('vmSize')]", } + } } - ``` ### Configure with Bicep To deploy an ML - compute that complies with this rule: -- Set the `disableLocalAuth` property value to `true`. +- Set the `properties.disableLocalAuth` property to `true`. For example: diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index e33b4715ced..01dd4f68f43 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -2,8 +2,8 @@ reviewed: 2023-10-12 severity: Critical pillar: Security -category: Networking -resource: ML +category: Connectivity +resource: Machine Learning online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.WrkspPublicAccess/ --- @@ -11,55 +11,56 @@ online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.Wrk ## SYNOPSIS -Disable public network access from a ML - Workspace. +Disable public network access from a ML - Workspace. ## DESCRIPTION -Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. You can control exposure of your workspaces by creating private endpoints instead. +Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. +You can control exposure of your workspaces by creating private endpoints instead. ## RECOMMENDATION -Consider setting the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled", as part of a broader security strategy. +Consider setting the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled", as part of a broader security strategy. ## EXAMPLES ### Configure with Azure template -To deploy an ML - Workspace that complies with this rule: +To deploy an ML - Workspace that passes this rule: -- update the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled". +- Set the `properties.publicNetworkAccess` property to `Disabled`. For example: ```json { - "type": "Microsoft.MachineLearningServices/workspaces", - "apiVersion": "2023-04-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "sku": { - "name": "basic", - "tier": "basic" - }, - "identity": { - "type": "SystemAssigned" - }, - "properties": { - "friendlyName": "[parameters('name')]", - "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", - "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", - "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", - "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", - "publicNetworkAccess": "Disabled" - } - + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "sku": { + "name": "basic", + "tier": "basic" + }, + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('name')]", + "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", + "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", + "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", + "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", + "publicNetworkAccess": "Disabled" + } +} ``` ### Configure with Bicep -To deploy an ML - Workspace that complies with this rule: +To deploy an ML - Workspace that passes this rule: -- update the 'publicNetworkAccess' parameter of the Workspace properties to 'Disabled'. +- Set the `properties.publicNetworkAccess` property to `Disabled`. For example: @@ -83,13 +84,12 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' publicNetworkAccess: 'Disabled' } } - ``` ## LINKS +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) - [Configure a private endpoint for an Azure Machine Learning workspace](https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=cli) - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) -- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md index 34c8a96930f..10cb93ab790 100644 --- a/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md +++ b/docs/en/rules/Azure.ML.WrkspVnetPubAccess.md @@ -2,8 +2,8 @@ reviewed: 2023-10-12 severity: Critical pillar: Security -category: Networking -resource: ML +category: Connectivity +resource: Machine Learning online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.WrkspVnetPubAccess/ --- @@ -11,15 +11,15 @@ online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.Wrk ## SYNOPSIS -Disable public network access from a ML - Workspace when behind a VNet. +Disable public network access from a ML - Workspace when behind a VNet. ## DESCRIPTION -Disable public network access from a ML - Workspace when behind a VNet. +Disable public network access from a ML - Workspace when behind a VNet. ## RECOMMENDATION -Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false, as part of a broader security strategy. +Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false, as part of a broader security strategy. ## EXAMPLES @@ -27,39 +27,39 @@ Consider setting the 'allowPublicAccessWhenBehindVnet' parameter of the Workspac To deploy an ML - Workspace that complies with this rule: -- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. +- Set the `properties.allowPublicAccessWhenBehindVnet` property to `false`. For example: ```json { - "type": "Microsoft.MachineLearningServices/workspaces", - "apiVersion": "2023-04-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "sku": { - "name": "basic", - "tier": "basic" - }, - "identity": { - "type": "SystemAssigned" - }, - "properties": { - "friendlyName": "[parameters('name')]", - "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", - "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", - "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", - "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", - "allowPublicAccessWhenBehindVnet": false - } - + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "sku": { + "name": "basic", + "tier": "basic" + }, + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('name')]", + "keyVault": "[resourceId('Microsoft.KeyVault/vaults', parameters('KeyVaultName'))]", + "storageAccount": "[resourceId('Microsoft.Storage/storageAccounts', parameters('StorageAccountName'))]", + "applicationInsights": "[resourceId('Microsoft.Insights/components', parameters('AppInsightsName'))]", + "containerRegistry": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('ContainerRegistryName'))]", + "allowPublicAccessWhenBehindVnet": false + } +} ``` ### Configure with Bicep To deploy an ML - Workspace that complies with this rule: -- update the 'allowPublicAccessWhenBehindVnet' parameter of the Workspace properties to false. +- Set the `properties.allowPublicAccessWhenBehindVnet` property to `false`. For example: @@ -83,11 +83,11 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' allowPublicAccessWhenBehindVnet: false } } - ``` ## LINKS + +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) -- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) diff --git a/docs/examples-ML.bicep b/docs/examples-ML.bicep index d46d457e776..8e285039489 100644 --- a/docs/examples-ML.bicep +++ b/docs/examples-ML.bicep @@ -25,15 +25,15 @@ resource mlWorkspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' e name: 'example-ws' } -resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ +resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' = { name: '${mlWorkspace.name}/${name}' location: location - properties:{ + properties: { managedResourceGroupId: managedRg.id computeType: 'ComputeInstance' properties: { - vmSize: vmSize - idleTimeBeforeShutdown: idleTimeBeforeShutdown + vmSize: vmSize + idleTimeBeforeShutdown: idleTimeBeforeShutdown } } } From 9dbc7c6bdc9307871cb6f302e96aaa67fc8a916e Mon Sep 17 00:00:00 2001 From: Bernie White Date: Sun, 15 Oct 2023 14:07:37 +0000 Subject: [PATCH 16/22] Other minor updates --- docs/CHANGELOG-v1.md | 10 ++++++++++ docs/en/rules/Azure.ML.DisableLocalAuth.md | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG-v1.md b/docs/CHANGELOG-v1.md index aed6df05873..0f6c785e60b 100644 --- a/docs/CHANGELOG-v1.md +++ b/docs/CHANGELOG-v1.md @@ -30,6 +30,16 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers What's changed since v1.30.2: +- New rules: + - Machine Learning: + - Check that compute has an idle shutdown set by @batemansogq. + [#2484](https://github.com/Azure/PSRule.Rules.Azure/issues/2484) + - Check compute SSH keys are disabled by @batemansogq. + [#2484](https://github.com/Azure/PSRule.Rules.Azure/issues/2484) + - Check compute is connected to a VNET by @batemansogq. + [#2484](https://github.com/Azure/PSRule.Rules.Azure/issues/2484) + - Check public workspace endpoints are disabled by @batemansogq. + [#2484](https://github.com/Azure/PSRule.Rules.Azure/issues/2484) - Engineering: - Bump development tools to .NET 7.0 SDK by @BernieWhite. [#1870](https://github.com/Azure/PSRule.Rules.Azure/issues/1870) diff --git a/docs/en/rules/Azure.ML.DisableLocalAuth.md b/docs/en/rules/Azure.ML.DisableLocalAuth.md index b559c012126..87dee2faf78 100644 --- a/docs/en/rules/Azure.ML.DisableLocalAuth.md +++ b/docs/en/rules/Azure.ML.DisableLocalAuth.md @@ -3,7 +3,7 @@ reviewed: 2023-10-10 severity: Critical pillar: Security category: Identity and Access Management -resource: ML +resource: Machine Learning online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ML.DisableLocalAuth/ --- @@ -57,7 +57,6 @@ To deploy an ML - compute that complies with this rule: For example: ```bicep - resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/computes@2023-04-01' ={ name: '${mlWorkspace.name}/${name}' location: location From 1f924adcb0a71f6210bb5c19f3d4b9e7d1225abb Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:32:21 +1100 Subject: [PATCH 17/22] Update docs/en/rules/Azure.ML.WrkspPublicAccess.md Co-authored-by: Bernie White --- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index 01dd4f68f43..c9b487d69da 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -17,7 +17,14 @@ Disable public network access from a ML - Workspace. Disabling public network access improves security by ensuring that the Machine Learning Workspaces aren't exposed on the public internet. You can control exposure of your workspaces by creating private endpoints instead. - +By default, a public endpoint is enabled for Machine Learning workspaces. +The public endpoint is used for all access except for requests that use a Private Endpoint. +Access through the public endpoint can be disabled or restricted to authorized virtual networks. + +Data exfiltration is an attack where an malicious actor does an unauthorized data transfer. +Private Endpoints help control exposure of a workspace to data exfiltration by an internal or external malicious actor. +They do this by providing clear separation between public and private endpoints. +As a result, broad access to public endpoints which could be operated by a malicious actor are not required. ## RECOMMENDATION Consider setting the 'publicNetworkAccess' parameter of the Workspace properties to "Disabled", as part of a broader security strategy. From 1717e7283df639807fe2660734d06c4c7ea57662 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:32:34 +1100 Subject: [PATCH 18/22] Update docs/en/rules/Azure.ML.ComputeIdleShutdown.md Co-authored-by: Bernie White --- docs/en/rules/Azure.ML.ComputeIdleShutdown.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md index ac41f68cba0..9685f378736 100644 --- a/docs/en/rules/Azure.ML.ComputeIdleShutdown.md +++ b/docs/en/rules/Azure.ML.ComputeIdleShutdown.md @@ -45,7 +45,7 @@ For example: "computeType": "ComputeInstance", "properties": { "vmSize": "[parameters('vmSize')]", - "idleTimeBeforeShutdown": "[parameters('idleTimeBeforeShutdown')]" + "idleTimeBeforeShutdown": "PT15M" } } } From b743b02a06b1395f6f121826592ee66bc945c264 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:32:47 +1100 Subject: [PATCH 19/22] Update docs/en/rules/Azure.ML.WrkspPublicAccess.md Co-authored-by: Bernie White --- docs/en/rules/Azure.ML.WrkspPublicAccess.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/rules/Azure.ML.WrkspPublicAccess.md b/docs/en/rules/Azure.ML.WrkspPublicAccess.md index c9b487d69da..3492dced9cc 100644 --- a/docs/en/rules/Azure.ML.WrkspPublicAccess.md +++ b/docs/en/rules/Azure.ML.WrkspPublicAccess.md @@ -99,4 +99,5 @@ resource Ml_Workspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' - [Configure a private endpoint for an Azure Machine Learning workspace](https://learn.microsoft.com/azure/machine-learning/how-to-configure-private-link?view=azureml-api-2&tabs=cli) - [ML - Public access to Workspaces](https://learn.microsoft.com/azure/machine-learning/how-to-secure-workspace-vnet?view=azureml-api-2&tabs=required%2Cpe%2Ccli#public-access-to-workspace) - [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep#workspaceproperties) +- [NS-2: Secure cloud services with network controls](https://learn.microsoft.com/security/benchmark/azure/baselines/machine-learning-service-security-baseline#ns-2-secure-cloud-services-with-network-controls) - [Security and governance for ML](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2) From cdcb7c0a729bac30814b57c3b2424331184c7c18 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:33:27 +1100 Subject: [PATCH 20/22] Update docs/en/rules/Azure.ML.ComputeVnet.md Co-authored-by: Bernie White --- docs/en/rules/Azure.ML.ComputeVnet.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/en/rules/Azure.ML.ComputeVnet.md b/docs/en/rules/Azure.ML.ComputeVnet.md index 271186e06de..902adb4c2c4 100644 --- a/docs/en/rules/Azure.ML.ComputeVnet.md +++ b/docs/en/rules/Azure.ML.ComputeVnet.md @@ -79,9 +79,10 @@ resource aml_compute_instance 'Microsoft.MachineLearningServices/workspaces/comp ## LINKS +- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) - [Managed compute in a managed virtual network](https://learn.microsoft.com/azure/machine-learning/how-to-managed-network-compute?view=azureml-api-2&tabs=azure-cli) - [ML - Network security and isolation](https://learn.microsoft.com/azure/machine-learning/concept-enterprise-security?view=azureml-api-2#network-security-and-isolation) -- [ML - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes?pivots=deployment-language-bicep#resource-format) -- [ML - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces?pivots=deployment-language-bicep) - [ML Compute](https://learn.microsoft.com/azure/machine-learning/azure-machine-learning-glossary?view=azureml-api-2#compute) -- [WAF - Azure services for securing network connectivity](https://learn.microsoft.com/azure/well-architected/security/design-network-connectivity) +- [NS-1: Establish network segmentation boundaries](https://learn.microsoft.com/security/benchmark/azure/baselines/machine-learning-service-security-baseline#ns-1-establish-network-segmentation-boundaries) +- [Azure deployment reference - Workspaces](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/2023-04-01/workspaces) +- [Azure deployment reference - Compute objects](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces/computes#resource-format) From f4905c58a9a63336f432db45352c407d18590189 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:33:48 +1100 Subject: [PATCH 21/22] Update src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml Co-authored-by: Bernie White --- src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index affa91cb5f1..6c63adf1f5c 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -54,6 +54,8 @@ metadata: release: GA ruleSet: 2023_10 Azure.WAF/pillar: Security + labels: + Azure.MCSB.v1/control: [ 'NS-1' ] spec: type: - Microsoft.MachineLearningServices/workspaces/computes From 5792480566064099ce7657b0ffbb601d9b13d686 Mon Sep 17 00:00:00 2001 From: batemansogq Date: Wed, 18 Oct 2023 09:33:57 +1100 Subject: [PATCH 22/22] Update src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml Co-authored-by: Bernie White --- src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml index 6c63adf1f5c..a7e70967836 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml +++ b/src/PSRule.Rules.Azure/rules/Azure.ML.Rule.yaml @@ -52,7 +52,7 @@ metadata: ref: AZR-000405 tags: release: GA - ruleSet: 2023_10 + ruleSet: 2023_12 Azure.WAF/pillar: Security labels: Azure.MCSB.v1/control: [ 'NS-1' ]