Родитель
a498afb287
Коммит
60c532e365
|
@ -5,6 +5,10 @@
|
|||
- Added new rules for Traffic Manager:
|
||||
- Check web-based endpoints are monitored with HTTPS. [#240](https://github.com/Microsoft/PSRule.Rules.Azure/issues/240)
|
||||
- Check at least two endpoints are enabled. [#241](https://github.com/Microsoft/PSRule.Rules.Azure/issues/241)
|
||||
- Added new rules for Key Vault:
|
||||
- Check soft delete is enabled. [#277](https://github.com/Microsoft/PSRule.Rules.Azure/issues/277)
|
||||
- Check purge protection is enabled. [#280](https://github.com/Microsoft/PSRule.Rules.Azure/issues/280)
|
||||
- Check least privileges permissions assigned in access policy. [#281](https://github.com/Microsoft/PSRule.Rules.Azure/issues/281)
|
||||
|
||||
## v0.9.0-B2002019 (pre-release)
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
severity: Important
|
||||
category: Security operations
|
||||
resource: Key Vault
|
||||
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.KeyVault.AccessPolicy.md
|
||||
---
|
||||
|
||||
# Limit access to Key Vault data
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
Use the principal of least privilege when assigning access to Key Vault.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Key Vault is a service designed to securely store sensitive items such as secrets, keys and certificates.
|
||||
Access Policies determine the permissions user accounts, groups or applications have to Key Vaults items.
|
||||
|
||||
The ability for applications and administrators to get, set and list within a Key Vault is commonly required.
|
||||
However should only be assigned to security principals that require access.
|
||||
The purge permission should be rarely assigned.
|
||||
|
||||
## RECOMMENDATION
|
||||
|
||||
Consider assigning access to Key Vault data based on the principle of least privilege.
|
||||
|
||||
## LINKS
|
||||
|
||||
- [Security recommendations for Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/security-recommendations)
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
severity: Important
|
||||
category: Data recovery
|
||||
resource: Key Vault
|
||||
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.KeyVault.PurgeProtect.md
|
||||
---
|
||||
|
||||
# Use Key Vault Purge Protection
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
Enable Purge Protection on Key Vaults to prevent early purge of vaults and vault items.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Purge Protection is a feature of Key Vault that prevents purging of vaults and vault items.
|
||||
When soft delete is configured without purge protection, deleted vaults and vault items can be purged.
|
||||
Purging deletes the vault and/ or vault items immediately, and is irreversible.
|
||||
|
||||
When purge protection is enabled, vaults and vault items can no longer be purged.
|
||||
Deleted vaults and vault items will be recoverable until the configured retention period.
|
||||
By default, the retention period is 90 days.
|
||||
|
||||
Purge protection is not enabled by default.
|
||||
|
||||
## RECOMMENDATION
|
||||
|
||||
Consider enabling purge protection on Key Vaults to enforce retention of vaults and vault items for up to 90 days.
|
||||
|
||||
## LINKS
|
||||
|
||||
- [Azure Key Vault soft-delete overview](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-ovw-soft-delete)
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
severity: Important
|
||||
category: Data recovery
|
||||
resource: Key Vault
|
||||
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.KeyVault.SoftDelete.md
|
||||
---
|
||||
|
||||
# Use Key Vault Soft Delete
|
||||
|
||||
## SYNOPSIS
|
||||
|
||||
Enable Soft Delete on Key Vaults to protect vaults and vault items from accidental deletion.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Soft Delete is a feature of Key Vault that retains Key Vaults and Key Vault items after initial deletion.
|
||||
A soft deleted vault or vault item can be restored within the configured retention period.
|
||||
|
||||
By default, new Key Vaults created through the portal will have soft delete for 90 days configured.
|
||||
|
||||
Once enabled, soft delete can not be disabled.
|
||||
When soft delete is enabled, it is possible to purge soft deleted vaults and vault items.
|
||||
|
||||
## RECOMMENDATION
|
||||
|
||||
Consider enabling soft delete on Key Vaults to enable recovery of vaults and vault items.
|
||||
|
||||
## LINKS
|
||||
|
||||
- [Azure Key Vault soft-delete overview](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-ovw-soft-delete)
|
||||
- [Security recommendations for Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/security-recommendations)
|
|
@ -15,4 +15,5 @@
|
|||
BackendUrlNotHttps = "The backend URL for '{0}' is not a HTTPS endpoint."
|
||||
ResourceNotAssociated = "The resource is not associated."
|
||||
EnabledEndpoints = "The number of enabled endpoints is {0}."
|
||||
AccessPolicyLeastPrivilege = "One or more access policies grant all or purge permission."
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Validation rules for Key Vault
|
||||
#
|
||||
|
||||
# Synopsis: Enable Key Vault Soft Delete
|
||||
Rule 'Azure.KeyVault.SoftDelete' -Type 'Microsoft.KeyVault/vaults' -Tag @{ release = 'GA' } {
|
||||
$Assert.HasFieldValue($TargetObject, 'Properties.enableSoftDelete', $True)
|
||||
}
|
||||
|
||||
# Synopsis: Enable Key Vault Purge Protection
|
||||
Rule 'Azure.KeyVault.PurgeProtect' -Type 'Microsoft.KeyVault/vaults' -Tag @{ release = 'GA' } {
|
||||
$Assert.HasFieldValue($TargetObject, 'Properties.enablePurgeProtection', $True)
|
||||
}
|
||||
|
||||
# Synopsis: Limit access to Key Vault data
|
||||
Rule 'Azure.KeyVault.AccessPolicy' -Type 'Microsoft.KeyVault/vaults', 'Microsoft.KeyVault/vaults/accessPolicies' -Tag @{ release = 'GA' } {
|
||||
Reason $LocalizedData.AccessPolicyLeastPrivilege;
|
||||
$accessPolicies = @($TargetObject);
|
||||
if ($PSRule.TargetType -eq 'Microsoft.KeyVault/vaults') {
|
||||
$accessPolicies = @($TargetObject.Properties.accessPolicies);
|
||||
}
|
||||
if ($accessPolicies.Length -eq 0) {
|
||||
return $True;
|
||||
}
|
||||
foreach ($policy in $accessPolicies) {
|
||||
$policy.permissions.keys -notin 'All', 'Purge'
|
||||
$policy.permissions.secrets -notin 'All', 'Purge'
|
||||
$policy.permissions.certificates -notin 'All', 'Purge'
|
||||
$policy.permissions.storage -notin 'All', 'Purge'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Unit tests for Key Vault rules
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
|
||||
)
|
||||
|
||||
# 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.KeyVault' -Tag 'KeyVault' {
|
||||
$dataPath = Join-Path -Path $here -ChildPath 'Resources.KeyVault.json';
|
||||
|
||||
Context 'Conditions' {
|
||||
$invokeParams = @{
|
||||
Baseline = 'Azure.All'
|
||||
Module = 'PSRule.Rules.Azure'
|
||||
WarningAction = 'Ignore'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
$result = Invoke-PSRule @invokeParams -InputPath $dataPath -Outcome All;
|
||||
|
||||
It 'Azure.KeyVault.SoftDelete' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.KeyVault.SoftDelete' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'keyvault-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 2;
|
||||
$ruleResult.TargetName | Should -BeIn 'keyvault-A', 'keyvault-C';
|
||||
}
|
||||
|
||||
It 'Azure.KeyVault.PurgeProtect' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.KeyVault.PurgeProtect' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 2;
|
||||
$ruleResult.TargetName | Should -BeIn 'keyvault-B', 'keyvault-C';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -BeIn 'keyvault-A';
|
||||
}
|
||||
|
||||
It 'Azure.KeyVault.AccessPolicy' {
|
||||
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.KeyVault.AccessPolicy' };
|
||||
|
||||
# Fail
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
# $ruleResult.Length | Should -Be 1;
|
||||
$ruleResult.TargetName | Should -Be 'keyvault-B';
|
||||
|
||||
# Pass
|
||||
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
|
||||
$ruleResult | Should -Not -BeNullOrEmpty;
|
||||
$ruleResult.Length | Should -Be 2;
|
||||
$ruleResult.TargetName | Should -BeIn 'keyvault-A', 'keyvault-C';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
[
|
||||
{
|
||||
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-A",
|
||||
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-A",
|
||||
"Identity": null,
|
||||
"Kind": null,
|
||||
"Location": "region",
|
||||
"ManagedBy": null,
|
||||
"ResourceName": "keyvault-A",
|
||||
"Name": "keyvault-A",
|
||||
"Properties": {
|
||||
"sku": {
|
||||
"family": "A",
|
||||
"name": "Premium"
|
||||
},
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"accessPolicies": [
|
||||
{
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"objectId": "00000000-0000-0000-0000-000000000000",
|
||||
"permissions": {
|
||||
"certificates": [
|
||||
"Get",
|
||||
"List"
|
||||
],
|
||||
"keys": [
|
||||
"Get",
|
||||
"List"
|
||||
],
|
||||
"secrets": [
|
||||
"Get",
|
||||
"List",
|
||||
"Set"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"enabledForDeployment": true,
|
||||
"enabledForDiskEncryption": true,
|
||||
"enabledForTemplateDeployment": true,
|
||||
"enableSoftDelete": true,
|
||||
"enablePurgeProtection": true,
|
||||
"vaultUri": "https://keyvault-A.vault.azure.net/",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"ResourceGroupName": "rg-test",
|
||||
"Type": "Microsoft.KeyVault/vaults",
|
||||
"ResourceType": "Microsoft.KeyVault/vaults",
|
||||
"Sku": null,
|
||||
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-B",
|
||||
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-B",
|
||||
"Identity": null,
|
||||
"Kind": null,
|
||||
"Location": "region",
|
||||
"ManagedBy": null,
|
||||
"ResourceName": "keyvault-B",
|
||||
"Name": "keyvault-B",
|
||||
"Properties": {
|
||||
"sku": {
|
||||
"family": "A",
|
||||
"name": "Premium"
|
||||
},
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"accessPolicies": [
|
||||
{
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"objectId": "00000000-0000-0000-0000-000000000000",
|
||||
"permissions": {
|
||||
"certificates": [
|
||||
"All"
|
||||
],
|
||||
"keys": [
|
||||
"All"
|
||||
],
|
||||
"secrets": [
|
||||
"Get",
|
||||
"Set",
|
||||
"List",
|
||||
"Purge"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"enabledForDeployment": true,
|
||||
"enabledForDiskEncryption": true,
|
||||
"enabledForTemplateDeployment": true,
|
||||
"enableSoftDelete": false,
|
||||
"vaultUri": "https://keyvault-B.vault.azure.net/",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"ResourceGroupName": "rg-test",
|
||||
"Type": "Microsoft.KeyVault/vaults",
|
||||
"ResourceType": "Microsoft.KeyVault/vaults",
|
||||
"Sku": null,
|
||||
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
|
||||
},
|
||||
{
|
||||
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-C",
|
||||
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.KeyVault/vaults/keyvault-C",
|
||||
"Identity": null,
|
||||
"Kind": null,
|
||||
"Location": "region",
|
||||
"ManagedBy": null,
|
||||
"ResourceName": "keyvault-C",
|
||||
"Name": "keyvault-C",
|
||||
"Properties": {
|
||||
"sku": {
|
||||
"family": "A",
|
||||
"name": "Premium"
|
||||
},
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"accessPolicies": [
|
||||
],
|
||||
"enabledForDeployment": true,
|
||||
"enabledForDiskEncryption": true,
|
||||
"enabledForTemplateDeployment": true,
|
||||
"enableSoftDelete": true,
|
||||
"enablePurgeProtection": false,
|
||||
"vaultUri": "https://keyvault-C.vault.azure.net/",
|
||||
"provisioningState": "Succeeded"
|
||||
},
|
||||
"ResourceGroupName": "rg-test",
|
||||
"Type": "Microsoft.KeyVault/vaults",
|
||||
"ResourceType": "Microsoft.KeyVault/vaults",
|
||||
"Sku": null,
|
||||
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
]
|
Загрузка…
Ссылка в новой задаче