Skip to content

Commit

Permalink
Use SHA-512 for name generation #1155 (#1575)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Jul 16, 2023
1 parent ff44545 commit bb41e56
Show file tree
Hide file tree
Showing 25 changed files with 276 additions and 86 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ The following conceptual topics exist in the `PSRule` module:
- [Execution.AliasReference](https://aka.ms/ps-rule/options#executionaliasreference)
- [Execution.AliasReferenceWarning](https://aka.ms/ps-rule/options#executionaliasreferencewarning)
- [Execution.DuplicateResourceId](https://aka.ms/ps-rule/options#executionduplicateresourceid)
- [Execution.HashAlgorithm](https://aka.ms/ps-rule/options#executionhashalgorithm)
- [Execution.LanguageMode](https://aka.ms/ps-rule/options#executionlanguagemode)
- [Execution.InconclusiveWarning](https://aka.ms/ps-rule/options#executioninconclusivewarning)
- [Execution.InvariantCulture](https://aka.ms/ps-rule/options#executioninvariantculture)
Expand Down
7 changes: 7 additions & 0 deletions docs/CHANGELOG-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
What's changed since release v2.9.0:

- General improvements:
- **Breaking change:** Switch to use SHA-512 for generating unbound objects by @BernieWhite.
[#1155](https://github.com/microsoft/PSRule/issues/1155)
- Objects that have no bound name will automatically be assigned a name based on the SHA-512 hash of the object.
- Previously a SHA-1 hash was used, however this is no longer considered secure.
- The name for unbound objects that are suppressed will change as a result.
- Additionally the hash can be changed by setting the `Execution.HashAlgorithm` option.
- See [upgrade notes][1] for details.
- Expanded support for `FileHeader` assertion by @BernieWhite.
[#1521](https://github.com/microsoft/PSRule/issues/1521)
- Added support for `.bicepparam`, `.tsp`, `.tsx`, `.editorconfig`, `.ipynb`, and `.toml` files.
Expand Down
69 changes: 61 additions & 8 deletions docs/concepts/PSRule/en-US/about_PSRule_Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The following workspace options are available for use:
- [Execution.AliasReference](#executionaliasreference)
- [Execution.AliasReferenceWarning](#executionaliasreferencewarning)
- [Execution.DuplicateResourceId](#executionduplicateresourceid)
- [Execution.HashAlgorithm](#executionhashalgorithm)
- [Execution.LanguageMode](#executionlanguagemode)
- [Execution.InconclusiveWarning](#executioninconclusivewarning)
- [Execution.InvariantCulture](#executioninvariantculture)
Expand Down Expand Up @@ -88,7 +89,8 @@ Options can be used with the following PSRule cmdlets:

Each of these cmdlets support:

- Using the `-Option` parameter with an object created with the `New-PSRuleOption` cmdlet. See cmdlet help for syntax and examples.
- Using the `-Option` parameter with an object created with the `New-PSRuleOption` cmdlet.
See cmdlet help for syntax and examples.
- Using the `-Option` parameter with a hashtable object.
- Using the `-Option` parameter with a YAML file path.

Expand Down Expand Up @@ -124,7 +126,8 @@ The `Set-PSRuleOption` cmdlet can be used to set options stored in YAML or the Y
Set-PSRuleOption -OutputFormat Yaml;
```

By default, PSRule will automatically look for a default YAML options file in the current working directory. Alternatively, you can specify a specific file path.
By default, PSRule will automatically look for a default YAML options file in the current working directory.
Alternatively, you can specify a specific file path.

For example:

Expand Down Expand Up @@ -426,21 +429,25 @@ _TargetName_ is used in output results to identify one object from another.
Many objects could be passed down the pipeline at the same time, so using a _TargetName_ that is meaningful is important.
_TargetName_ is also used for advanced features such as rule suppression.

The value that PSRule uses for _TargetName_ is configurable. PSRule uses the following logic to determine what _TargetName_ should be used:
The value that PSRule uses for _TargetName_ is configurable.
PSRule uses the following logic to determine what _TargetName_ should be used:

- By default PSRule will:
- Use `TargetName` or `Name` properties on the object. These property names are case insensitive.
- If both `TargetName` and `Name` properties exist, `TargetName` will take precedence over `Name`.
- If neither `TargetName` or `Name` properties exist, a SHA1 hash of the object will be used as _TargetName_.
- If neither `TargetName` or `Name` properties exist, a hash of the object will be used as _TargetName_.
- The hash algorithm used can be set by the `Execution.HashAlgorithm` option.
- If custom _TargetName_ binding properties are configured, the property names specified will override the defaults.
- If **none** of the configured property names exist, PSRule will revert back to `TargetName` then `Name`.
- If more then one property name is configured, the order they are specified in the configuration determines precedence.
- i.e. The first configured property name will take precedence over the second property name.
- By default the property name will be matched ignoring case sensitivity. To use a case sensitive match, configure the [Binding.IgnoreCase](#bindingignorecase) option.
- By default the property name will be matched ignoring case sensitivity.
To use a case sensitive match, configure the [Binding.IgnoreCase](#bindingignorecase) option.
- If a custom _TargetName_ binding function is specified, the function will be evaluated first before any other option.
- If the function returns `$Null` then custom properties, `TargetName` and `Name` properties will be used.
- The custom binding function is executed outside the PSRule engine, so PSRule keywords and variables will not be available.
- Custom binding functions are blocked in constrained language mode is used. See [language mode](#executionlanguagemode) for more information.
- Custom binding functions are blocked in constrained language mode is used.
See [language mode](#executionlanguagemode) for more information.

Custom property names to use for binding can be specified using:

Expand Down Expand Up @@ -515,11 +522,13 @@ PSRule uses the following logic to determine what _TargetType_ should be used:
- If **none** of the configured property names exist, PSRule will revert back to the type presented by PowerShell.
- If more then one property name is configured, the order they are specified in the configuration determines precedence.
- i.e. The first configured property name will take precedence over the second property name.
- By default the property name will be matched ignoring case sensitivity. To use a case sensitive match, configure the [`Binding.IgnoreCase`](#bindingignorecase) option.
- By default the property name will be matched ignoring case sensitivity.
To use a case sensitive match, configure the [`Binding.IgnoreCase`](#bindingignorecase) option.
- If a custom _TargetType_ binding function is specified, the function will be evaluated first before any other option.
- If the function returns `$Null` then custom properties, or the type presented by PowerShell will be used in order instead.
- The custom binding function is executed outside the PSRule engine, so PSRule keywords and variables will not be available.
- Custom binding functions are blocked in constrained language mode is used. See [language mode](#executionlanguagemode) for more information.
- Custom binding functions are blocked in constrained language mode is used.
See [language mode](#executionlanguagemode) for more information.

Custom property names to use for binding can be specified using:

Expand Down Expand Up @@ -897,6 +906,50 @@ variables:
value: Warn
```

### Execution.HashAlgorithm

Specifies the hashing algorithm used by the PSRule runtime.
This hash algorithm is used when generating a resource identifier for an object that does not have a bound name.

By default, the _SHA512_ algorithm is used.

The following algorithms are available for use in PSRule:

- SHA512
- SHA384
- SHA256

This option can be specified using:

```powershell
# PowerShell: Using the Execution.HashAlgorithm hashtable key
$option = New-PSRuleOption -Option @{ 'Execution.HashAlgorithm' = 'SHA256' };
```

```yaml
# YAML: Using the execution/hashAlgorithm property
execution:
hashAlgorithm: SHA256
```

```bash
# Bash: Using environment variable
export PSRULE_EXECUTION_HASHALGORITHM=SHA256
```

```yaml
# GitHub Actions: Using environment variable
env:
PSRULE_EXECUTION_HASHALGORITHM: SHA256
```

```yaml
# Azure Pipelines: Using environment variable
variables:
- name: PSRULE_EXECUTION_HASHALGORITHM
value: SHA256
```

### Execution.LanguageMode

Unless PowerShell has been constrained, full language features of PowerShell are available to use within rule definitions.
Expand Down
21 changes: 21 additions & 0 deletions docs/upgrade-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ discussion: false

This document contains notes to help upgrade from previous versions of PSRule.

## Upgrading to v3.0.0

### Unbound object names

When an object is processed by PSRule, it is assigned a name.
This name is used to identify the object in the output and to suppress the object from future processing.

Prior to _v3.0.0_, the name was generated using a SHA-1 hash of the object.
The SHA-1 algorithm is no longer considered secure and has been replaced with SHA-512.

From _v3.0.0_, if the name of an object can not be determined, the SHA-512 hash of the object will be used.
Any objects that have previously been suppressed with a name based on a SHA-1 hash will no longer be suppressed.

To resolve any issue caused by this change, you can:

1. Configure binding by setting the [Binding.TargetName][1] option to set an alternative property to use as the name. _OR_
2. Update any existing keys set with the [Suppression][2] option to use the new SHA-512 hash.

[1]: https://aka.ms/ps-rule/options#bindingtargetname
[2]: https://aka.ms/ps-rule/options#suppression

## Upgrading to v2.0.0

### Resources naming restrictions
Expand Down
12 changes: 12 additions & 0 deletions schemas/PSRule-options.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,18 @@
],
"default": "Error"
},
"hashAlgorithm": {
"type": "string",
"title": "Hash Algorithm",
"description": "Configures the hashing algorithm used by the PSRule runtime. By default, SHA512 is used.",
"markdownDescription": "Configures the hashing algorithm used by the PSRule runtime.\n\nBy default, `SHA512` is used.\n\n[See help](https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Options/#executionhashalgorithm)",
"enum": [
"SHA512",
"SHA384",
"SHA256"
],
"default": "SHA512"
},
"languageMode": {
"type": "string",
"title": "Language mode",
Expand Down
2 changes: 1 addition & 1 deletion src/PSRule.Tool/ClientHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private static PSRuleOption GetOption(ClientHost host)
{
PSRuleOption.UseHostContext(host);
var option = PSRuleOption.FromFileOrEmpty();
option.Execution.InitialSessionState = Configuration.SessionState.Minimal;
option.Execution.InitialSessionState = Options.SessionState.Minimal;
option.Input.Format = InputFormat.File;
option.Output.Style ??= OutputStyle.Client;
return option;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Configuration
namespace PSRule.Options
{
/// <summary>
/// Determines the action to take for execution behaviors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.ComponentModel;

namespace PSRule.Configuration
namespace PSRule.Options
{
/// <summary>
/// Options that configure the execution sandbox.
Expand All @@ -13,7 +13,7 @@ namespace PSRule.Configuration
/// </remarks>
public sealed class ExecutionOption : IEquatable<ExecutionOption>
{
private const LanguageMode DEFAULT_LANGUAGEMODE = Configuration.LanguageMode.FullLanguage;
private const LanguageMode DEFAULT_LANGUAGEMODE = Options.LanguageMode.FullLanguage;
private const ExecutionActionPreference DEFAULT_DUPLICATERESOURCEID = ExecutionActionPreference.Error;
private const SessionState DEFAULT_INITIALSESSIONSTATE = SessionState.BuiltIn;
private const ExecutionActionPreference DEFAULT_SUPPRESSIONGROUPEXPIRED = ExecutionActionPreference.Warn;
Expand All @@ -23,10 +23,12 @@ public sealed class ExecutionOption : IEquatable<ExecutionOption>
private const ExecutionActionPreference DEFAULT_RULEINCONCLUSIVE = ExecutionActionPreference.Warn;
private const ExecutionActionPreference DEFAULT_INVARIANTCULTURE = ExecutionActionPreference.Warn;
private const ExecutionActionPreference DEFAULT_UNPROCESSEDOBJECT = ExecutionActionPreference.Warn;
private const HashAlgorithm DEFAULT_HASHALGORITHM = Options.HashAlgorithm.SHA512;

internal static readonly ExecutionOption Default = new()
{
DuplicateResourceId = DEFAULT_DUPLICATERESOURCEID,
HashAlgorithm = DEFAULT_HASHALGORITHM,
LanguageMode = DEFAULT_LANGUAGEMODE,
InitialSessionState = DEFAULT_INITIALSESSIONSTATE,
SuppressionGroupExpired = DEFAULT_SUPPRESSIONGROUPEXPIRED,
Expand All @@ -46,6 +48,7 @@ public ExecutionOption()
#pragma warning disable CS0618 // Type or member is obsolete
AliasReferenceWarning = null;
DuplicateResourceId = null;
HashAlgorithm = null;
LanguageMode = null;
InconclusiveWarning = null;
InvariantCultureWarning = null;
Expand Down Expand Up @@ -74,6 +77,7 @@ public ExecutionOption(ExecutionOption option)
#pragma warning disable CS0618 // Type or member is obsolete
AliasReferenceWarning = option.AliasReferenceWarning;
DuplicateResourceId = option.DuplicateResourceId;
HashAlgorithm = option.HashAlgorithm;
LanguageMode = option.LanguageMode;
InconclusiveWarning = option.InconclusiveWarning;
InvariantCultureWarning = option.InvariantCultureWarning;
Expand Down Expand Up @@ -103,6 +107,7 @@ public bool Equals(ExecutionOption other)
return other != null &&
AliasReferenceWarning == other.AliasReferenceWarning &&
DuplicateResourceId == other.DuplicateResourceId &&
HashAlgorithm == other.HashAlgorithm &&
LanguageMode == other.LanguageMode &&
InconclusiveWarning == other.InconclusiveWarning &&
InvariantCultureWarning == other.InvariantCultureWarning &&
Expand All @@ -128,6 +133,7 @@ public override int GetHashCode()
#pragma warning disable CS0618 // Type or member is obsolete
hash = hash * 23 + (AliasReferenceWarning.HasValue ? AliasReferenceWarning.Value.GetHashCode() : 0);
hash = hash * 23 + (DuplicateResourceId.HasValue ? DuplicateResourceId.Value.GetHashCode() : 0);
hash = hash * 23 + (HashAlgorithm.HasValue ? HashAlgorithm.Value.GetHashCode() : 0);
hash = hash * 23 + (LanguageMode.HasValue ? LanguageMode.Value.GetHashCode() : 0);
hash = hash * 23 + (InconclusiveWarning.HasValue ? InconclusiveWarning.Value.GetHashCode() : 0);
hash = hash * 23 + (InvariantCultureWarning.HasValue ? InvariantCultureWarning.Value.GetHashCode() : 0);
Expand Down Expand Up @@ -157,6 +163,7 @@ internal static ExecutionOption Combine(ExecutionOption o1, ExecutionOption o2)
{
AliasReferenceWarning = o1.AliasReferenceWarning ?? o2.AliasReferenceWarning,
DuplicateResourceId = o1.DuplicateResourceId ?? o2.DuplicateResourceId,
HashAlgorithm = o1.HashAlgorithm ?? o2.HashAlgorithm,
LanguageMode = o1.LanguageMode ?? o2.LanguageMode,
InconclusiveWarning = o1.InconclusiveWarning ?? o2.InconclusiveWarning,
NotProcessedWarning = o1.NotProcessedWarning ?? o2.NotProcessedWarning,
Expand Down Expand Up @@ -192,6 +199,12 @@ internal static ExecutionOption Combine(ExecutionOption o1, ExecutionOption o2)
[DefaultValue(null)]
public ExecutionActionPreference? DuplicateResourceId { get; set; }

/// <summary>
/// Configures the hashing algorithm used by the PSRule runtime.
/// </summary>
[DefaultValue(null)]
public HashAlgorithm? HashAlgorithm { get; set; }

/// <summary>
/// The langauge mode to execute PowerShell code with.
/// </summary>
Expand Down Expand Up @@ -330,6 +343,9 @@ internal static ExecutionOption Combine(ExecutionOption o1, ExecutionOption o2)
/// </summary>
internal void Load()
{
if (Environment.TryEnum("PSRULE_EXECUTION_HASHALGORITHM", out HashAlgorithm hashAlgorithm))
HashAlgorithm = hashAlgorithm;

#pragma warning disable CS0618 // Type or member is obsolete
if (Environment.TryBool("PSRULE_EXECUTION_ALIASREFERENCEWARNING", out var bvalue))
AliasReferenceWarning = bvalue;
Expand Down Expand Up @@ -383,6 +399,9 @@ internal void Load()
/// </summary>
internal void Load(Dictionary<string, object> index)
{
if (index.TryPopEnum("Execution.HashAlgorithm", out HashAlgorithm hashAlgorithm))
HashAlgorithm = hashAlgorithm;

#pragma warning disable CS0618 // Type or member is obsolete
if (index.TryPopBool("Execution.AliasReferenceWarning", out var bvalue))
AliasReferenceWarning = bvalue;
Expand Down
30 changes: 30 additions & 0 deletions src/PSRule.Types/Options/HashAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace PSRule.Options
{
/// <summary>
/// Configures the hashing algorithm used by the PSRule runtime.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum HashAlgorithm
{
/// <summary>
/// Use SHA256.
/// </summary>
SHA256,

/// <summary>
/// Use SHA384.
/// </summary>
SHA384,

/// <summary>
/// Use SHA512.
/// </summary>
SHA512
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Configuration
namespace PSRule.Options
{
/// <summary>
/// Configures the language mode PowerShell code executes as within PSRule runtime.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace PSRule.Configuration
namespace PSRule.Options
{
/// <summary>
/// Configures how the initial PowerShell sandbox for executing rules is created.
Expand Down
2 changes: 1 addition & 1 deletion src/PSRule/Common/RunspaceContextDiagnosticExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Configuration;
using PSRule.Options;
using PSRule.Definitions;
using PSRule.Pipeline;
using PSRule.Resources;
Expand Down
Loading

0 comments on commit bb41e56

Please sign in to comment.