Fixes for policy as rule and policy ignore #1731 #181 #1323 (#2720)

This commit is contained in:
Bernie White 2024-03-04 01:37:43 +10:00 коммит произвёл GitHub
Родитель 56ebaf3baa
Коммит 036db3dfaa
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
17 изменённых файлов: 548 добавлений и 54 удалений

10
.vscode/markdown.code-snippets поставляемый
Просмотреть файл

@ -140,5 +140,15 @@
"",
"```"
]
},
"rule-azure-example-policy": {
"scope": "markdown",
"prefix": "rule-azure-example-policy",
"description": "Example for Azure Policy",
"body": [
"### Configure with Azure Policy",
"",
"To address this issue at runtime use the following policies:"
]
}
}

1
.vscode/yaml.code-snippets поставляемый
Просмотреть файл

@ -1,5 +1,6 @@
{
"Azure rule with type": {
"scope": "yaml",
"prefix": "rule-azure-with-type",
"description": "Rule definition for Azure",
"body": [

Просмотреть файл

@ -165,6 +165,42 @@
"/providers/Microsoft.Authorization/policyDefinitions/cfdc5972-75b3-4418-8ae1-7f5c36839390"
],
"reason": "Duplicate",
"value": "Azure.Defender.Storage.SensitiveData"
"value": "Azure.Defender.Storage.DataScan"
},
{
"policyDefinitionIds": [
"/providers/Microsoft.Authorization/policyDefinitions/0e80e269-43a4-4ae9-b5bc-178126b8a5cb"
],
"reason": "Duplicate",
"value": "Azure.ContainerApp.Insecure"
},
{
"policyDefinitionIds": [
"/providers/Microsoft.Authorization/policyDefinitions/b874ab2d-72dd-47f1-8cb5-4a306478a4e7"
],
"reason": "Duplicate",
"value": "Azure.ContainerApp.ManagedIdentity"
},
{
"policyDefinitionIds": [
"/providers/Microsoft.Authorization/policyDefinitions/13502221-8df0-4414-9937-de9c5c4e396b"
],
"reason": "Duplicate",
"value": "Azure.Storage.BlobPublicAccess"
},
{
"policyDefinitionIds": [
"/providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9",
"/providers/Microsoft.Authorization/policyDefinitions/f81e3117-0093-4b17-8a60-82363134f0eb"
],
"reason": "Duplicate",
"value": "Azure.Storage.SecureTransfer"
},
{
"policyDefinitionIds": [
"/providers/Microsoft.Authorization/policyDefinitions/fe83a0eb-a853-422d-aac2-1bffd182c5d0"
],
"reason": "Duplicate",
"value": "Azure.Storage.MinTLS"
}
]

Просмотреть файл

@ -48,9 +48,16 @@ What's changed since pre-release v1.34.0-B0047:
- Renamed `Azure.Storage.DefenderCloud.SensitiveData` to `Azure.Storage.Defender.DataScan`.
- Promoted `Azure.Storage.Defender.MalwareScan` to GA rule set by @BernieWhite.
[#2590](https://github.com/Azure/PSRule.Rules.Azure/pull/2590)
- General improvements:
- Added duplicate policies to default ignore list by @BernieWhite.
[#1731](https://github.com/Azure/PSRule.Rules.Azure/issues/1731)
- Engineering:
- Updated resource providers and policy aliases.
[#2717](https://github.com/Azure/PSRule.Rules.Azure/pull/2717)
- Bug fixes:
- Fixes for policy as rules by @BernieWhite.
[#181](https://github.com/Azure/PSRule.Rules.Azure/issues/181)
[#1323](https://github.com/Azure/PSRule.Rules.Azure/issues/1323)
## v1.34.0-B0047 (pre-release)

Просмотреть файл

@ -95,10 +95,10 @@ resource account 'Microsoft.CognitiveServices/accounts@2023-05-01' = {
To address this issue at runtime use the following policies:
```text
/providers/Microsoft.Authorization/policyDefinitions/71ef260a-8f18-47b7-abcb-62d0673d94dc
/providers/Microsoft.Authorization/policyDefinitions/14de9e63-1b31-492e-a5a3-c3f7fd57f555
```
- [Azure AI Services resources should have key access disabled (disable local authentication)](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Azure%20Ai%20Services/CognitiveServices_DisableLocalAuth_Audit.json)
`/providers/Microsoft.Authorization/policyDefinitions/71ef260a-8f18-47b7-abcb-62d0673d94dc`
- [Configure Cognitive Services accounts to disable local authentication methods](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Cognitive%20Services/CognitiveServices_DisableLocalAuth_Modify.json)
`/providers/Microsoft.Authorization/policyDefinitions/14de9e63-1b31-492e-a5a3-c3f7fd57f555`
## LINKS

Просмотреть файл

@ -1,8 +1,8 @@
---
reviewed: 2023-04-29
reviewed: 2024-03-04
severity: Important
pillar: Security
category: Design
category: SE:07 Encryption
resource: Container App
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ContainerApp.Insecure/
---
@ -98,9 +98,16 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
}
```
### Configure with Azure Policy
To address this issue at runtime use the following policies:
- [Container Apps should only be accessible over HTTPS](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Container%20Apps/ContainerApps_EnableHTTPS_Audit.json)
`/providers/Microsoft.Authorization/policyDefinitions/0e80e269-43a4-4ae9-b5bc-178126b8a5cb`
## LINKS
- [Data encryption in Azure](https://learn.microsoft.com/azure/architecture/framework/security/design-storage-encryption#data-in-transit)
- [Ingress in Azure Container Apps](https://learn.microsoft.com/azure/container-apps/ingress-overview#configuration)
- [SE:07 Encryption](https://learn.microsoft.com/azure/well-architected/security/encryption#data-in-transit)
- [Ingress in Azure Container Apps](https://learn.microsoft.com/azure/container-apps/ingress-overview)
- [Container Apps ARM template API specification](https://learn.microsoft.com/azure/container-apps/azure-resource-manager-api-spec?tabs=arm-template)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.app/containerapps)

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
pillar: Security
category: Authentication
category: SE:05 Identity and access management
resource: Container App
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ContainerApp.ManagedIdentity/
---
@ -16,10 +16,13 @@ Ensure managed identity is used for authentication.
Using managed identities have the following benefits:
- Your app connects to resources with the managed identity. You don't need to manage credentials in your container app.
- Your app connects to resources with the managed identity.
You don't need to manage credentials in your container app.
- You can use role-based access control to grant specific permissions to a managed identity.
- System-assigned identities are automatically created and managed. They're deleted when your container app is deleted.
- You can add and delete user-assigned identities and assign them to multiple resources. They're independent of your container app's life cycle.
- System-assigned identities are automatically created and managed.
They're deleted when your container app is deleted.
- You can add and delete user-assigned identities and assign them to multiple resources.
They're independent of your container app's life cycle.
- You can use managed identity to authenticate with a private Azure Container Registry without a username and password to pull containers for your Container App.
- You can use managed identity to create connections for Dapr-enabled applications via Dapr components.
@ -102,6 +105,13 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
}
```
### Configure with Azure Policy
To address this issue at runtime use the following policies:
- [Managed Identity should be enabled for Container Apps](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Container%20Apps/ContainerApps_ManagedIdentity_Audit.json)
`/providers/Microsoft.Authorization/policyDefinitions/b874ab2d-72dd-47f1-8cb5-4a306478a4e7`
## NOTES
Using managed identities in scale rules isn't supported.
@ -109,6 +119,6 @@ Init containers can't access managed identities.
## LINKS
- [Use identity-based authentication](https://learn.microsoft.com/azure/well-architected/security/design-identity-authentication#use-identity-based-authentication)
- [SE:05 Identity and access management](https://learn.microsoft.com/azure/well-architected/security/identity-access)
- [Managed identities in Azure Container Apps](https://learn.microsoft.com/azure/container-apps/managed-identity)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.app/containerapps#managedserviceidentity)

Просмотреть файл

@ -1,8 +1,8 @@
---
reviewed: 2022-01-20
reviewed: 2024-03-04
severity: Important
pillar: Security
category: Authentication
category: SE:05 Identity and access management
resource: Storage Account
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Storage.BlobAccessType/
---
@ -40,16 +40,16 @@ For example:
```json
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2021-06-01",
"name": "[format('{0}/{1}/{2}', parameters('name'), 'default', variables('containerName'))]",
"properties": {
"publicAccess": "None"
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('name'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('name'))]"
]
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2021-06-01",
"name": "[format('{0}/{1}/{2}', parameters('name'), 'default', variables('containerName'))]",
"properties": {
"publicAccess": "None"
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('name'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('name'))]"
]
}
```
@ -73,8 +73,10 @@ resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@20
## LINKS
- [Authentication with Azure AD](https://learn.microsoft.com/azure/architecture/framework/security/design-identity-authentication)
- [About anonymous public read access](https://docs.microsoft.com/azure/storage/blobs/anonymous-read-access-configure#about-anonymous-public-read-access)
- [Use Azure Policy to enforce authorized access](https://docs.microsoft.com/azure/storage/blobs/anonymous-read-access-prevent#use-azure-policy-to-enforce-authorized-access)
- [How a shared access signature works](https://docs.microsoft.com/azure/storage/common/storage-sas-overview#how-a-shared-access-signature-works)
- [SE:05 Identity and access management](https://learn.microsoft.com/azure/well-architected/security/identity-access)
- [Use Microsoft Entra ID for storage authentication](https://learn.microsoft.com/azure/security/fundamentals/identity-management-best-practices#use-microsoft-entra-id-for-storage-authentication)
- [Configure anonymous read access for containers and blobs](https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-configure)
- [Remediate anonymous read access to blob data](https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-prevent)
- [How a shared access signature works](https://learn.microsoft.com/azure/storage/common/storage-sas-overview#how-a-shared-access-signature-works)
- [Authorize access to blobs using Microsoft Entra ID](https://learn.microsoft.com/azure/storage/blobs/authorize-access-azure-active-directory)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.storage/storageaccounts)

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
pillar: Security
category: Authentication
category: SE:05 Identity and access management
resource: Storage Account
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Storage.BlobPublicAccess/
---
@ -89,11 +89,18 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
}
```
### Configure with Azure Policy
To address this issue at runtime use the following policies:
- [Configure your Storage account public access to be disallowed](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Storage/StorageAccountDisablePublicBlobAccess_Modify.json)
`/providers/Microsoft.Authorization/policyDefinitions/13502221-8df0-4414-9937-de9c5c4e396b`
## LINKS
- [Use Azure AD for storage authentication](https://docs.microsoft.com/azure/security/fundamentals/identity-management-best-practices#use-azure-ad-for-storage-authentication)
- [Allow or disallow public read access for a storage account](https://docs.microsoft.com/azure/storage/blobs/anonymous-read-access-configure#allow-or-disallow-public-read-access-for-a-storage-account)
- [Remediate anonymous public access](https://docs.microsoft.com/azure/storage/blobs/anonymous-read-access-prevent#remediate-anonymous-public-access)
- [Use Azure Policy to enforce authorized access](https://docs.microsoft.com/azure/storage/blobs/anonymous-read-access-prevent#use-azure-policy-to-enforce-authorized-access)
- [Authorize access to blobs using Azure Active Directory](https://docs.microsoft.com/azure/storage/blobs/authorize-access-azure-active-directory)
- [SE:05 Identity and access management](https://learn.microsoft.com/azure/well-architected/security/identity-access)
- [Use Microsoft Entra ID for storage authentication](https://learn.microsoft.com/azure/security/fundamentals/identity-management-best-practices#use-microsoft-entra-id-for-storage-authentication)
- [Configure anonymous read access for containers and blobs](https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-configure)
- [Remediate anonymous read access to blob data](https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-prevent)
- [Authorize access to blobs using Microsoft Entra ID](https://learn.microsoft.com/azure/storage/blobs/authorize-access-azure-active-directory)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.storage/storageaccounts)

Просмотреть файл

@ -1,7 +1,8 @@
---
reviewed: 2024-03-04
severity: Critical
pillar: Security
category: Encryption
category: SE:07 Encryption
resource: Storage Account
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Storage.MinTLS/
---
@ -87,9 +88,16 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
}
```
### Configure with Azure Policy
To address this issue at runtime use the following policies:
- [Storage accounts should have the specified minimum TLS version](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Storage/StorageAccountMinimumTLSVersion_Audit.json)
`/providers/Microsoft.Authorization/policyDefinitions/fe83a0eb-a853-422d-aac2-1bffd182c5d0`
## LINKS
- [Data encryption in Azure](https://learn.microsoft.com/azure/architecture/framework/security/design-storage-encryption#data-in-transit)
- [SE:07 Encryption](https://learn.microsoft.com/azure/well-architected/security/encryption#data-in-transit)
- [TLS encryption in Azure](https://learn.microsoft.com/azure/security/fundamentals/encryption-overview#tls-encryption-in-azure)
- [Enforce a minimum required version of Transport Layer Security (TLS) for requests to a storage account](https://learn.microsoft.com/azure/storage/common/transport-layer-security-configure-minimum-version)
- [DP-3: Encrypt sensitive data in transit](https://learn.microsoft.com/security/benchmark/azure/baselines/storage-security-baseline#dp-3-encrypt-sensitive-data-in-transit)

Просмотреть файл

@ -1,8 +1,8 @@
---
reviewed: 2023-09-02
reviewed: 2024-03-04
severity: Important
pillar: Security
category: Encryption
category: SE:07 Encryption
resource: Storage Account
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Storage.SecureTransfer/
ms-content-id: 539cb7b9-5510-4aa3-b422-41a049a10a88
@ -101,9 +101,18 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
}
```
### Configure with Azure Policy
To address this issue at runtime use the following policies:
- [Secure transfer to storage accounts should be enabled](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Storage/Storage_AuditForHTTPSEnabled_Audit.json)
`/providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9`
- [Configure secure transfer of data on a storage account](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/Storage/StorageAccountSecureTransfer_Modify.json)
`/providers/Microsoft.Authorization/policyDefinitions/f81e3117-0093-4b17-8a60-82363134f0eb`
## LINKS
- [Data encryption in Azure](https://learn.microsoft.com/azure/architecture/framework/security/design-storage-encryption#data-in-transit)
- [SE:07 Encryption](https://learn.microsoft.com/azure/well-architected/security/encryption#data-in-transit)
- [Require secure transfer in Azure Storage](https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer)
- [DP-3: Encrypt sensitive data in transit](https://learn.microsoft.com/security/benchmark/azure/baselines/storage-security-baseline#dp-3-encrypt-sensitive-data-in-transit)
- [Sample policy for ensuring https traffic](https://learn.microsoft.com/azure/governance/policy/samples/built-in-policies#storage)

Просмотреть файл

@ -1001,7 +1001,7 @@ namespace PSRule.Rules.Azure.Data.Policy
{
if (condition.TryStringProperty(PROPERTY_VALUE, out var s) && s.IsExpressionString())
{
VisitValueExpression(context, condition, s);
condition = VisitValueExpression(context, condition, s);
}
else if (condition.TryStringProperty(PROPERTY_FIELD, out var field))
{
@ -1248,7 +1248,7 @@ namespace PSRule.Rules.Azure.Data.Policy
}
}
private static void VisitValueExpression(PolicyAssignmentContext context, JObject condition, string s)
private static JObject VisitValueExpression(PolicyAssignmentContext context, JObject condition, string s)
{
var tokens = ExpressionParser.Parse(s);
@ -1288,7 +1288,24 @@ namespace PSRule.Rules.Azure.Data.Policy
}
// Handle [field('string')]
else if (tokens.ConsumeFunction(PROPERTY_FIELD) &&
else if (tokens.HasFieldTokens())
{
condition = VisitFieldTokens(context, condition, tokens);
}
// Handle runtime token
else if (tokens.HasPolicyRuntimeTokens())
{
var value = VisitRuntimeTokens(context, tokens);
if (value != null)
condition.ReplaceProperty(PROPERTY_VALUE, value);
}
return condition;
}
private static JObject VisitFieldTokens(PolicyAssignmentContext context, JObject condition, TokenStream tokens)
{
if (tokens.ConsumeFunction(PROPERTY_FIELD) &&
tokens.TryTokenType(ExpressionTokenType.GroupStart, out _) &&
tokens.ConsumeString(out var field) &&
tokens.TryTokenType(ExpressionTokenType.GroupEnd, out _))
@ -1302,17 +1319,68 @@ namespace PSRule.Rules.Azure.Data.Policy
else
{
condition.Remove(PROPERTY_VALUE);
field = context.TryPolicyAliasPath(field, out var aliasPath) ? TrimFieldName(context, aliasPath) : field;
condition.Add(PROPERTY_FIELD, field);
}
}
// Handle runtime token
else if (tokens.HasPolicyRuntimeTokens())
else if (tokens.ConsumeFunction("if") &&
tokens.TryTokenType(ExpressionTokenType.GroupStart, out _))
{
var value = VisitRuntimeTokens(context, tokens);
if (value != null)
condition.ReplaceProperty(PROPERTY_VALUE, value);
var orginal = condition;
// Condition
var leftCondition = VisitFieldTokens(context, new JObject(), tokens);
var rightCondition = ReverseCondition(Clone(leftCondition));
var leftEvaluation = VisitFieldTokens(context, Clone(orginal), tokens);
var rightEvaluation = VisitFieldTokens(context, Clone(orginal), tokens);
var left = new JObject
{
{ PROPERTY_FIELD, DOT },
{ PROPERTY_WHERE, leftCondition },
{ PROPERTY_ALLOF, new JArray(new[] { leftEvaluation }) }
};
var right = new JObject
{
{ PROPERTY_FIELD, DOT },
{ PROPERTY_WHERE, rightCondition },
{ PROPERTY_ALLOF, new JArray(new[] { rightEvaluation }) }
};
var result = OrCondition(left, right);
condition.Replace(result);
tokens.TryTokenType(ExpressionTokenType.GroupEnd, out _);
return result;
}
else if (tokens.ConsumeFunction(PROPERTY_EQUALS) &&
tokens.TryTokenType(ExpressionTokenType.GroupStart, out _))
{
VisitFieldTokens(context, condition, tokens);
if (tokens.ConsumeString(out var s))
{
condition.Add(PROPERTY_EQUALS, s);
}
tokens.TryTokenType(ExpressionTokenType.GroupEnd, out _);
}
else if (tokens.ConsumeFunction("empty") &&
tokens.TryTokenType(ExpressionTokenType.GroupStart, out _))
{
if (condition.TryBoolProperty(PROPERTY_EQUALS, out var emptyEquals))
{
condition.Remove(PROPERTY_EQUALS);
condition.Add("hasValue", !emptyEquals.Value);
}
VisitFieldTokens(context, condition, tokens);
tokens.TryTokenType(ExpressionTokenType.GroupEnd, out _);
}
return condition;
}
private static JObject VisitRuntimeTokens(PolicyAssignmentContext context, TokenStream tokens)
@ -1540,6 +1608,11 @@ namespace PSRule.Rules.Azure.Data.Policy
return condition;
}
private static JObject Clone(JObject o)
{
return o.DeepClone() as JObject;
}
private static JObject AlwaysFail(string effect)
{
return new JObject
@ -1564,7 +1637,7 @@ namespace PSRule.Rules.Azure.Data.Policy
/// </summary>
private static JObject DefaultEffectConditions(PolicyAssignmentContext context, JObject details)
{
return AndNameCondition(details, TypeExpression(context, details));
return AndNameCondition(context, details, TypeExpression(context, details));
}
private static JObject TypeExpression(PolicyAssignmentContext context, JObject details)
@ -1612,11 +1685,13 @@ namespace PSRule.Rules.Azure.Data.Policy
return existenceCondition;
}
private static JObject AndNameCondition(JObject details, JObject condition)
private static JObject AndNameCondition(PolicyAssignmentContext context, JObject details, JObject condition)
{
if (details == null || !details.TryStringProperty(PROPERTY_NAME, out var name))
return condition;
name = TemplateVisitor.ExpandString(context, name);
var nameCondition = new JObject {
{ PROPERTY_NAME, DOT },
{ PROPERTY_EQUALS, name }
@ -1641,6 +1716,23 @@ namespace PSRule.Rules.Azure.Data.Policy
return left == null || left.Count == 0 ? right : left;
}
private static JObject OrCondition(JObject left, JObject right)
{
if (left != null && left.Count > 0 && right != null && right.Count > 0)
{
var allOf = new JArray
{
left,
right
};
return new JObject
{
{ PROPERTY_ANYOF, allOf }
};
}
return left == null || left.Count == 0 ? right : left;
}
private static bool TryPolicyRuleEffect(PolicyAssignmentContext context, JObject then, out string effect)
{
ResolveObject(context, then);

Просмотреть файл

@ -202,6 +202,14 @@ namespace PSRule.Rules.Azure.Data.Template
return true;
}
internal static bool HasFieldTokens(this TokenStream stream)
{
return stream.ToArray().Any(t =>
t.Type == ExpressionTokenType.Element &&
string.Equals("field", t.Content, StringComparison.OrdinalIgnoreCase)
);
}
internal static bool HasPolicyRuntimeTokens(this TokenStream stream)
{
return stream.ToArray().Any(t =>

Просмотреть файл

@ -41,6 +41,9 @@
<None Update="Policy.assignment.4.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Policy.assignment.5.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Policy.assignment.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

Просмотреть файл

@ -0,0 +1,273 @@
[
{
"Identity": null,
"Location": null,
"Name": "assignment.5",
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/assignment.5",
"ResourceName": "assignment.5",
"ResourceGroupName": null,
"ResourceType": "Microsoft.Authorization/policyAssignments",
"SubscriptionId": "00000000-0000-0000-0000-000000000000",
"Sku": null,
"PolicyAssignmentId": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/assignment.5",
"Properties": {
"Scope": "/subscriptions/00000000-0000-0000-0000-000000000000",
"NotScopes": [],
"DisplayName": "Deploy Diagnostic Settings for Key Vault to Log Analytics workspace",
"Description": null,
"Metadata": {
"assignedBy": "",
"parameterScopes": {},
"createdBy": "",
"createdOn": "",
"updatedBy": null,
"updatedOn": null
},
"EnforcementMode": 1,
"PolicyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/bef3f64c-5290-43b7-85b0-9b254eef4c47",
"Parameters": {
"logAnalytics": {
"value": "test_workspace_id"
}
},
"NonComplianceMessages": []
},
"PolicyDefinitions": [
{
"Name": "bef3f64c-5290-43b7-85b0-9b254eef4c47",
"ResourceName": "bef3f64c-5290-43b7-85b0-9b254eef4c47",
"ResourceType": "Microsoft.Authorization/policyDefinitions",
"ResourceId": "/providers/Microsoft.Authorization/policyDefinitions/bef3f64c-5290-43b7-85b0-9b254eef4c47",
"SubscriptionId": null,
"Properties": {
"DisplayName": "Deploy Diagnostic Settings for Key Vault to Log Analytics workspace",
"PolicyType": 2,
"Mode": "Indexed",
"Description": "Deploys the diagnostic settings for Key Vault to stream to a regional Log Analytics workspace when any Key Vault which is missing this diagnostic settings is created or updated.",
"Metadata": {
"version": "3.0.0",
"category": "Monitoring"
},
"Version": "3.0.0",
"Parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"DeployIfNotExists",
"Disabled"
],
"defaultValue": "DeployIfNotExists"
},
"profileName": {
"type": "String",
"metadata": {
"displayName": "Profile name",
"description": "The diagnostic settings profile name"
},
"defaultValue": "setbypolicy_logAnalytics"
},
"logAnalytics": {
"type": "String",
"metadata": {
"displayName": "Log Analytics workspace",
"description": "Select Log Analytics workspace from dropdown list. If this workspace is outside of the scope of the assignment you must manually grant 'Log Analytics Contributor' permissions (or similar) to the policy assignment's principal ID.",
"strongType": "omsWorkspace",
"assignPermissions": true
}
},
"metricsEnabled": {
"type": "String",
"metadata": {
"displayName": "Enable metrics",
"description": "Whether to enable metrics stream to the Log Analytics workspace - True or False"
},
"allowedValues": [
"True",
"False"
],
"defaultValue": "False"
},
"logsEnabled": {
"type": "String",
"metadata": {
"displayName": "Enable logs",
"description": "Whether to enable logs stream to the Log Analytics workspace - True or False"
},
"allowedValues": [
"True",
"False"
],
"defaultValue": "True"
},
"matchWorkspace": {
"type": "Boolean",
"metadata": {
"displayName": "Workspace id must match",
"description": "Whether to require that the workspace of the diagnostic settings matches the workspace deployed by this policy"
},
"allowedValues": [
true,
false
],
"defaultValue": false
}
},
"PolicyRule": {
"if": {
"field": "type",
"equals": "Microsoft.KeyVault/vaults"
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"type": "Microsoft.Insights/diagnosticSettings",
"name": "[parameters('profileName')]",
"evaluationDelay": "AfterProvisioning",
"existenceCondition": {
"allOf": [
{
"count": {
"field": "Microsoft.Insights/diagnosticSettings/logs[*]",
"where": {
"allOf": [
{
"field": "Microsoft.Insights/diagnosticSettings/logs[*].enabled",
"equals": "[parameters('logsEnabled')]"
},
{
"field": "Microsoft.Insights/diagnosticSettings/logs[*].category",
"equals": "AuditEvent"
}
]
}
},
"greaterOrEquals": 1
},
{
"count": {
"field": "Microsoft.Insights/diagnosticSettings/metrics[*]",
"where": {
"field": "Microsoft.Insights/diagnosticSettings/metrics[*].enabled",
"equals": "[parameters('metricsEnabled')]"
}
},
"greaterOrEquals": 1
},
{
"anyOf": [
{
"value": "[parameters('matchWorkspace')]",
"equals": false
},
{
"field": "Microsoft.Insights/diagnosticSettings/workspaceId",
"equals": "[parameters('logAnalytics')]"
}
]
}
]
},
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa",
"/providers/microsoft.authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string"
},
"location": {
"type": "string"
},
"logAnalytics": {
"type": "string"
},
"metricsEnabled": {
"type": "string"
},
"logsEnabled": {
"type": "string"
},
"profileName": {
"type": "string"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.KeyVault/vaults/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(parameters('resourceName'), '/', 'Microsoft.Insights/', parameters('profileName'))]",
"location": "[parameters('location')]",
"dependsOn": [],
"properties": {
"workspaceId": "[parameters('logAnalytics')]",
"metrics": [
{
"category": "AllMetrics",
"enabled": "[parameters('metricsEnabled')]",
"retentionPolicy": {
"enabled": false,
"days": 0
}
}
],
"logs": [
{
"category": "AuditEvent",
"enabled": "[parameters('logsEnabled')]"
},
{
"category": "AzurePolicyEvaluationDetails",
"enabled": "[parameters('logsEnabled')]"
}
]
}
}
],
"outputs": {}
},
"parameters": {
"location": {
"value": "[field('location')]"
},
"resourceName": {
"value": "[field('name')]"
},
"logAnalytics": {
"value": "[parameters('logAnalytics')]"
},
"metricsEnabled": {
"value": "[parameters('metricsEnabled')]"
},
"logsEnabled": {
"value": "[parameters('logsEnabled')]"
},
"profileName": {
"value": "[parameters('profileName')]"
}
}
}
}
}
}
},
"Versions": [
"3.0.0"
]
},
"PolicyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/bef3f64c-5290-43b7-85b0-9b254eef4c47"
}
],
"exemptions": []
}
]

Просмотреть файл

@ -35,7 +35,7 @@ namespace PSRule.Rules.Azure
var definitions = context.GetDefinitions();
Assert.NotNull(definitions);
Assert.Equal(129, definitions.Length);
Assert.Equal(130, definitions.Length);
// Check category and version
var actual = definitions.FirstOrDefault(definition => definition.DefinitionId == "/providers/Microsoft.Authorization/policyDefinitions/34c877ad-507e-4c82-993e-3452a6e0ad3c");
@ -228,6 +228,27 @@ namespace PSRule.Rules.Azure
Assert.Equal(new string[] { "PSRule.Rules.Azure\\Azure.Policy.Indexed" }, actual.With);
}
[Fact]
public void ExpandDetailsName()
{
var context = new PolicyAssignmentContext(GetContext());
var visitor = new PolicyAssignmentDataExportVisitor();
foreach (var assignment in GetAssignmentData("Policy.assignment.5.json").Where(a => a["Name"].Value<string>() == "assignment.5"))
visitor.Visit(context, assignment);
var definitions = context.GetDefinitions();
Assert.NotNull(definitions);
Assert.Single(definitions);
var actual = definitions.FirstOrDefault(definition => definition.DefinitionId == "/providers/Microsoft.Authorization/policyDefinitions/bef3f64c-5290-43b7-85b0-9b254eef4c47");
Assert.NotNull(actual);
Assert.Single(actual.Types);
Assert.Equal("Microsoft.KeyVault/vaults", actual.Types[0]);
Assert.Null(actual.Where);
Assert.Equal("{\"allOf\":[{\"type\":\".\",\"equals\":\"Microsoft.Insights/diagnosticSettings\"},{\"name\":\".\",\"equals\":\"setbypolicy_logAnalytics\"}]}", actual.Condition["where"].ToString(Formatting.None));
Assert.Equal(new string[] { "PSRule.Rules.Azure\\Azure.Policy.Indexed" }, actual.With);
}
#region Helper methods
private static PipelineContext GetContext(PSRuleOption option = null)

Просмотреть файл

@ -25,13 +25,13 @@ namespace PSRule.Rules.Azure
Assert.Equal(PolicyIgnoreReason.Duplicate, entry.Reason);
Assert.Contains("Azure.Defender.Storage.MalwareScan", entry.Value);
Assert.Contains("Azure.Defender.Storage", entry.Value);
Assert.Contains("Azure.Defender.Storage.SensitiveData", entry.Value);
Assert.Contains("Azure.Defender.Storage.DataScan", entry.Value);
Assert.True(data.TryGetValue("/providers/Microsoft.Authorization/policyDefinitions/cfdc5972-75b3-4418-8ae1-7f5c36839390", out entry));
Assert.Equal(PolicyIgnoreReason.Duplicate, entry.Reason);
Assert.Contains("Azure.Defender.Storage.MalwareScan", entry.Value);
Assert.Contains("Azure.Defender.Storage", entry.Value);
Assert.Contains("Azure.Defender.Storage.SensitiveData", entry.Value);
Assert.Contains("Azure.Defender.Storage.DataScan", entry.Value);
}
#region Helper methods