Skip to content

Commit

Permalink
Added support for overriding rule severity level #1180 (#2621)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Nov 21, 2024
1 parent 11852a9 commit d5cdcfd
Show file tree
Hide file tree
Showing 59 changed files with 1,320 additions and 108 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ The following conceptual topics exist in the `PSRule` module:
- [Output.Path](https://aka.ms/ps-rule/options#outputpath)
- [Output.SarifProblemsOnly](https://aka.ms/ps-rule/options#outputsarifproblemsonly)
- [Output.Style](https://aka.ms/ps-rule/options#outputstyle)
- [Override.Level](https://aka.ms/ps-rule/options#overridelevel)
- [Repository.BaseRef](https://aka.ms/ps-rule/options#repositorybaseref)
- [Repository.Url](https://aka.ms/ps-rule/options#repositoryurl)
- [Requires](https://aka.ms/ps-rule/options#requires)
Expand Down
6 changes: 6 additions & 0 deletions docs/CHANGELOG-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

- New features:
- Added support for overriding rule severity level by @BernieWhite.
[#1180](https://github.com/microsoft/PSRule/issues/1180)
- Baselines now accept a new `spec.overrides.level` property which configures severity level overrides.
- Options now accept a new `overrides.level` properties which configures severity level overrides.
- For example, a rule that generates an `Error` can be overridden to `Warning`.
- General improvements:
- Automatically restore missing modules when running CLI by @BernieWhite.
[#2552](https://github.com/microsoft/PSRule/issues/2552)
Expand Down
7 changes: 5 additions & 2 deletions docs/concepts/PSRule/en-US/about_PSRule_Baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ A baseline includes a set of rule and configuration options that are used for ev
The following baseline options can be configured:

- [Configuration](about_PSRule_Options.md#configuration)
- [Override.Level](about_PSRule_Options.md#overridelevel)
- [Rule.Include](about_PSRule_Options.md#ruleinclude)
- [Rule.IncludeLocal](about_PSRule_Options.md#ruleincludelocal)
- [Rule.Exclude](about_PSRule_Options.md#ruleexclude)
Expand Down Expand Up @@ -48,8 +49,9 @@ metadata:
annotations: { }
spec:
# One or more baseline options
rule: { }
configuration: { }
override: {}
rule: { }
```
For example:
Expand Down Expand Up @@ -100,8 +102,9 @@ To define a JSON baseline spec use the following structure:
"annotations": {}
},
"spec": {
"configuration": {},
"override": {},
"rule": {},
"configuration": {}
}
}
]
Expand Down
56 changes: 56 additions & 0 deletions docs/concepts/PSRule/en-US/about_PSRule_Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ The following workspace options are available for use:
Additionally the following baseline options can be included:

- [Configuration](#configuration)
- [Override.Level](#overridelevel)
- [Rule.Baseline](#rulebaseline)
- [Rule.Include](#ruleinclude)
- [Rule.IncludeLocal](#ruleincludelocal)
Expand Down Expand Up @@ -3012,6 +3013,52 @@ variables:
value: 2
```

### Override.Level

This option is used to override the severity level of one or more rules.
When specified, the severity level of the rule will be set to the value specified.
Use this option to change the severity level of a rule to be different then originally defined by the author.

The following severity levels are available:

- `Error` - A serious problem that must be addressed before going forward.
- `Warning` - A problem that should be addressed.
- `Information` - A minor problem or an opportunity to improve the code.

This option can be specified using:

```powershell
# PowerShell: Using the OverrideLevel parameter
$option = New-PSRuleOption -OverrideLevel @{ 'rule1' = 'Information' };
```

```powershell
# PowerShell: Using the OVerride.Level hashtable key
$option = New-PSRuleOption -Option @{ 'Override.Level.rule1' = 'Information' };
```

```powershell
# PowerShell: Using the OverrideLevel parameter to set YAML
Set-PSRuleOption -OverrideLevel @{ 'rule1' = 'Information' };
```

```yaml
# YAML: Using the override/level property
override:
level:
rule1: Information
```

```bash
# Bash: Using environment variable
export PSRULE_OVERRIDE_LEVEL_RULE1='Information'
```

```powershell
# PowerShell: Using environment variable
$env:PSRULE_OVERRIDE_LEVEL_RULE1 = 'Information';
```

### Repository.BaseRef

This option is used for specify the base branch for pull requests.
Expand Down Expand Up @@ -3464,6 +3511,12 @@ output:
sarifProblemsOnly: false
style: GitHubActions
# Overrides the severity level for rules
override:
level:
Rule1: Error
Rule2: Warning
# Configure rule suppression
suppression:
storageAccounts.UseHttps:
Expand Down Expand Up @@ -3571,6 +3624,9 @@ output:
sarifProblemsOnly: true
style: Detect
override:
level: { }
# Configure rule suppression
suppression: { }
Expand Down
26 changes: 26 additions & 0 deletions docs/concepts/options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Options

Options are used to customize how rules are evaluated and the resulting output.
You can set options in multiple ways, including:

- Parameters
- Environment variables
- Configuration files

Rules or modules could also have a defaults configured by the rule or module author.

## Option precedence

When setting options, you may have a situation where an option is set to different values.
For example, you may set an option in a configuration file and also set the same option as a parameter.

When this happens, PSRule will use the option with the highest precedence.

Option precedence is as follows:

1. Parameters
2. Explicit baselines
3. Environment variables
4. Configuration files
5. Default baseline
6. Module defaults
19 changes: 19 additions & 0 deletions docs/concepts/sarif-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SARIF Output

PSRule uses a JSON structured output format called the

SARIF format to report results.
The SARIF format is a standard format for the output of static analysis tools.
The format is designed to be easily consumed by other tools and services.

## Runs

When running PSRule executed a run will be generated in `runs` containing details about PSRule and configuration details.

## Invocation

The `invocation` property reports runtime information about how the run started.

### RuleConfigurationOverrides

When a rule has been overridden in configuration this invocation property will contain any level overrides.
33 changes: 33 additions & 0 deletions schemas/PSRule-language.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,39 @@
}
},
"additionalProperties": false
},
"override": {
"type": "object",
"title": "Overrides",
"description": "Specifies additional rule overrides.",
"properties": {
"level": {
"type": "object",
"title": "Override severity level",
"description": "Overrides the severity level defined by the rule to the level specified. A rule can be configured with one of the following: Error, Warning, Information.",
"markdownDescription": "Overrides the severity level defined by the rule to the level specified.\n\nA rule can be configured with one of the following: `Error`, `Warning`, `Information`.\n\n[See help](https://microsoft.github.io/PSRule/v3/concepts/PSRule/en-US/about_PSRule_Options/#overridelevel)",
"additionalProperties": {
"type": "string",
"title": "Override level by rule",
"description": "Specify the new severity level of the rule. Choose one of the following supported values: Error, Warning, Information.",
"markdownDescription": "Specify the new severity level of the rule.\n\nChoose one of the following supported values: `Error`, `Warning`, `Information`.\n\n[See help](https://microsoft.github.io/PSRule/v3/concepts/PSRule/en-US/about_PSRule_Options/#overridelevel)",
"enum": [
"Error",
"Warning",
"Information"
]
},
"defaultSnippets": [
{
"label": "Override level",
"body": {
"${1:Rule}": "Error"
}
}
]
}
},
"additionalProperties": false
}
},
"additionalProperties": false
Expand Down
37 changes: 37 additions & 0 deletions schemas/PSRule-options.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,39 @@
},
"additionalProperties": false
},
"override-option": {
"type": "object",
"title": "Overrides",
"description": "Specifies additional rule overrides.",
"properties": {
"level": {
"type": "object",
"title": "Override severity level",
"description": "Overrides the severity level defined by the rule to the level specified. A rule can be configured with one of the following: Error, Warning, Information.",
"markdownDescription": "Overrides the severity level defined by the rule to the level specified.\n\nA rule can be configured with one of the following: `Error`, `Warning`, `Information`.\n\n[See help](https://microsoft.github.io/PSRule/v3/concepts/PSRule/en-US/about_PSRule_Options/#overridelevel)",
"additionalProperties": {
"type": "string",
"title": "Override level by rule",
"description": "Specify the new severity level of the rule. Choose one of the following supported values: Error, Warning, Information.",
"markdownDescription": "Specify the new severity level of the rule.\n\nChoose one of the following supported values: `Error`, `Warning`, `Information`.\n\n[See help](https://microsoft.github.io/PSRule/v3/concepts/PSRule/en-US/about_PSRule_Options/#overridelevel)",
"enum": [
"Error",
"Warning",
"Information"
]
},
"defaultSnippets": [
{
"label": "Override level",
"body": {
"${1:Rule}": "Error"
}
}
]
}
},
"additionalProperties": false
},
"options": {
"properties": {
"baseline": {
Expand Down Expand Up @@ -982,6 +1015,10 @@
"type": "object",
"$ref": "#/definitions/output-option"
},
"override": {
"type": "object",
"$ref": "#/definitions/override-option"
},
"repository": {
"type": "object",
"$ref": "#/definitions/repository-option"
Expand Down
14 changes: 14 additions & 0 deletions src/PSRule.Types/Converters/TypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,20 @@ public static bool TryDouble(object o, bool convert, out double value)
return false;
}

/// <summary>
/// Try to get the environment variable as a enum of type <typeparamref name="T"/>.
/// </summary>
public static bool TryEnum<T>(object o, bool convert, out T? value) where T : struct, Enum
{
if (o is T t || convert && o is string s && Enum.TryParse(s, ignoreCase: true, out t))
{
value = t;
return true;
}
value = null;
return false;
}

private static bool TryGetValue(object o, string propertyName, out object? value)
{
value = null;
Expand Down
72 changes: 72 additions & 0 deletions src/PSRule.Types/Data/EnumMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections;
using PSRule.Converters;

namespace PSRule.Data;

/// <summary>
/// A mapping of string to string arrays.
/// </summary>
public sealed class EnumMap<T> : KeyMap<T> where T : struct, Enum
{
/// <summary>
/// Create an empty <see cref="EnumMap{T}"/> instance.
/// </summary>
public EnumMap()
: base() { }

/// <summary>
/// Create an instance by copying an existing <see cref="EnumMap{T}"/>.
/// </summary>
internal EnumMap(EnumMap<T> map)
: base(map) { }

/// <summary>
/// Create an instance by copying mapped keys from a string dictionary.
/// </summary>
internal EnumMap(IDictionary<string, T> map)
: base(map) { }

/// <summary>
/// Create an instance by copying mapped keys from a <seealso cref="Hashtable"/>.
/// </summary>
/// <param name="map"></param>
internal EnumMap(Hashtable map)
: base(map) { }

/// <summary>
///
/// </summary>
/// <param name="hashtable"></param>
public static implicit operator EnumMap<T>(Hashtable hashtable)
{
return new EnumMap<T>(hashtable);
}

/// <summary>
/// Convert a hashtable into a <see cref="EnumMap{T}"/> instance.
/// </summary>
public static EnumMap<T> FromHashtable(Hashtable hashtable)
{
return new EnumMap<T>(hashtable);
}

/// <summary>
///
/// </summary>
/// <param name="o"></param>
/// <param name="value"></param>
/// <returns></returns>
protected override bool TryConvertValue(object o, out T value)
{
value = default;
if (TypeConverter.TryEnum<T>(o, convert: true, out var result) && result != null)
{
value = result.Value;
return true;
}
return false;
}
}
Loading

0 comments on commit d5cdcfd

Please sign in to comment.