diff --git a/Rules/Strings.Designer.cs b/Rules/Strings.Designer.cs index aae951eeb..c8bc1fe79 100644 --- a/Rules/Strings.Designer.cs +++ b/Rules/Strings.Designer.cs @@ -457,7 +457,7 @@ internal static string AvoidUsernameAndPasswordParamsCommonName { } /// - /// Looks up a localized string similar to Functions should only take in a credential parameter of type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute instead of username and password parameters.. + /// Looks up a localized string similar to Functions should take in a Credential parameter of type PSCredential (with a Credential transformation attribute defined after it in PowerShell 4.0 or earlier) or set the Password parameter to type SecureString.. /// internal static string AvoidUsernameAndPasswordParamsDescription { get { @@ -466,7 +466,7 @@ internal static string AvoidUsernameAndPasswordParamsDescription { } /// - /// Looks up a localized string similar to Function '{0}' has both username and password parameters. A credential parameter of type PSCredential with a CredentialAttribute where PSCredential comes before CredentialAttribute should be used.. + /// Looks up a localized string similar to Function '{0}' has both Username and Password parameters. Either set the type of the Password parameter to SecureString or replace the Username and Password parameters with a Credential parameter of type PSCredential. If using a Credential parameter in PowerShell 4.0 or earlier, please define a credential transformation attribute after the PSCredential type attribute.. /// internal static string AvoidUsernameAndPasswordParamsError { get { @@ -1834,7 +1834,7 @@ internal static string UseOutputTypeCorrectlyName { } /// - /// Looks up a localized string similar to PSCredential. + /// Looks up a localized string similar to Use PSCredential type.. /// internal static string UsePSCredentialTypeCommonName { get { @@ -1843,7 +1843,7 @@ internal static string UsePSCredentialTypeCommonName { } /// - /// Looks up a localized string similar to Checks that cmdlets that have a Credential parameter accept PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute.. This comes from the PowerShell teams best practices.. + /// Looks up a localized string similar to For PowerShell 4.0 and earlier, a parameter named Credential with type PSCredential must have a credential transformation attribute defined after the PSCredential type attribute. . /// internal static string UsePSCredentialTypeDescription { get { @@ -1852,7 +1852,7 @@ internal static string UsePSCredentialTypeDescription { } /// - /// Looks up a localized string similar to The Credential parameter in '{0}' must be of the type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute.. + /// Looks up a localized string similar to The Credential parameter in '{0}' must be of type PSCredential. For PowerShell 4.0 and earlier, please define a credential transformation attribute, e.g. [System.Management.Automation.Credential()], after the PSCredential type attribute.. /// internal static string UsePSCredentialTypeError { get { @@ -1861,7 +1861,7 @@ internal static string UsePSCredentialTypeError { } /// - /// Looks up a localized string similar to The Credential parameter in a found script block must be of the type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute.. + /// Looks up a localized string similar to The Credential parameter found in the script block must be of type PSCredential. For PowerShell 4.0 and earlier please define a credential transformation attribute, e.g. [System.Management.Automation.Credential()], after the PSCredential type attribute. . /// internal static string UsePSCredentialTypeErrorSB { get { diff --git a/Rules/Strings.resx b/Rules/Strings.resx index 233f99a5e..a7c969482 100644 --- a/Rules/Strings.resx +++ b/Rules/Strings.resx @@ -217,16 +217,16 @@ One Char - Checks that cmdlets that have a Credential parameter accept PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute.. This comes from the PowerShell teams best practices. + For PowerShell 4.0 and earlier, a parameter named Credential with type PSCredential must have a credential transformation attribute defined after the PSCredential type attribute. - The Credential parameter in '{0}' must be of the type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute. + The Credential parameter in '{0}' must be of type PSCredential. For PowerShell 4.0 and earlier, please define a credential transformation attribute, e.g. [System.Management.Automation.Credential()], after the PSCredential type attribute. - The Credential parameter in a found script block must be of the type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute. + The Credential parameter found in the script block must be of type PSCredential. For PowerShell 4.0 and earlier please define a credential transformation attribute, e.g. [System.Management.Automation.Credential()], after the PSCredential type attribute. - PSCredential + Use PSCredential type. Checks for reserved characters in cmdlet names. These characters usually cause a parsing error. Otherwise they will generally cause runtime errors. @@ -511,10 +511,10 @@ Avoid Using Username and Password Parameters - Functions should only take in a credential parameter of type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute instead of username and password parameters. + Functions should take in a Credential parameter of type PSCredential (with a Credential transformation attribute defined after it in PowerShell 4.0 or earlier) or set the Password parameter to type SecureString. - Function '{0}' has both username and password parameters. A credential parameter of type PSCredential with a CredentialAttribute where PSCredential comes before CredentialAttribute should be used. + Function '{0}' has both Username and Password parameters. Either set the type of the Password parameter to SecureString or replace the Username and Password parameters with a Credential parameter of type PSCredential. If using a Credential parameter in PowerShell 4.0 or earlier, please define a credential transformation attribute after the PSCredential type attribute. AvoidUsingUserNameAndPassWordParams diff --git a/Rules/UsePSCredentialType.cs b/Rules/UsePSCredentialType.cs index bddc3bf66..9f3c17377 100644 --- a/Rules/UsePSCredentialType.cs +++ b/Rules/UsePSCredentialType.cs @@ -24,13 +24,13 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules { /// - /// UsePSCredentialType: Analyzes the ast to check that cmdlets that have a Credential parameter accept PSCredential. + /// UsePSCredentialType: Checks if a parameter named Credential is of type PSCredential. Also checks if there is a credential transformation attribute defined after the PSCredential type attribute. The order between credential transformation attribute and PSCredential type attribute is applicable only to Poweshell 4.0 and earlier. /// [Export(typeof(IScriptRule))] public class UsePSCredentialType : IScriptRule { /// - /// AnalyzeScript: Analyzes the ast to check that cmdlets that have a Credential parameter accept PSCredential. + /// AnalyzeScript: Analyzes the ast to check if a parameter named Credential is of type PSCredential. Also checks if there is a credential transformation attribute defined after the PSCredential type attribute. The order between the credential transformation attribute and PSCredential type attribute is applicable only to Poweshell 4.0 and earlier. /// /// The script's ast /// The script's file name @@ -39,6 +39,15 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); + var sbAst = ast as ScriptBlockAst; + if (sbAst != null + && sbAst.ScriptRequirements != null + && sbAst.ScriptRequirements.RequiredPSVersion != null + && sbAst.ScriptRequirements.RequiredPSVersion.Major == 5) + { + yield break; + } + IEnumerable funcDefAsts = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true); IEnumerable scriptBlockAsts = ast.FindAll(testAst => testAst is ScriptBlockAst, true); diff --git a/Tests/Rules/AvoidUserNameAndPasswordParams.tests.ps1 b/Tests/Rules/AvoidUserNameAndPasswordParams.tests.ps1 index 555bc4ca9..df39b6931 100644 --- a/Tests/Rules/AvoidUserNameAndPasswordParams.tests.ps1 +++ b/Tests/Rules/AvoidUserNameAndPasswordParams.tests.ps1 @@ -1,6 +1,6 @@ Import-Module PSScriptAnalyzer -$violationMessage = "Function 'TestFunction' has both username and password parameters. A credential parameter of type PSCredential with a CredentialAttribute where PSCredential comes before CredentialAttribute should be used." +$violationMessage = "Function 'TestFunction' has both Username and Password parameters. Either set the type of the Password parameter to SecureString or replace the Username and Password parameters with a Credential parameter of type PSCredential. If using a Credential parameter in PowerShell 4.0 or earlier, please define a credential transformation attribute after the PSCredential type attribute." $violationName = "PSAvoidUsingUserNameAndPasswordParams" $directory = Split-Path -Parent $MyInvocation.MyCommand.Path $violations = Invoke-ScriptAnalyzer $directory\AvoidUserNameAndPasswordParams.ps1 | Where-Object {$_.RuleName -eq $violationName} @@ -13,7 +13,7 @@ Describe "AvoidUserNameAndPasswordParams" { } It "has the correct violation message" { - $violations[0].Message | Should Match $violationMessage + $violations[0].Message | Should Be $violationMessage } } diff --git a/Tests/Rules/PSCredentialType.ps1 b/Tests/Rules/PSCredentialType.ps1 index 3e2d9e730..f89ebdf01 100644 --- a/Tests/Rules/PSCredentialType.ps1 +++ b/Tests/Rules/PSCredentialType.ps1 @@ -14,7 +14,7 @@ function Credential2 [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] - [System.Management.Automation.CredentialAttribute()] + [System.Management.Automation.Credential()] [pscredential] $Credential ) diff --git a/Tests/Rules/PSCredentialType.tests.ps1 b/Tests/Rules/PSCredentialType.tests.ps1 index 852af655c..866e46a60 100644 --- a/Tests/Rules/PSCredentialType.tests.ps1 +++ b/Tests/Rules/PSCredentialType.tests.ps1 @@ -1,5 +1,5 @@ Import-Module PSScriptAnalyzer -$violationMessage = "The Credential parameter in 'Credential' must be of the type PSCredential with CredentialAttribute where PSCredential comes before CredentialAttribute." +$violationMessage = "The Credential parameter in 'Credential' must be of type PSCredential. For PowerShell 4.0 and earlier, please define a credential transformation attribute, e.g. [System.Management.Automation.Credential()], after the PSCredential type attribute." $violationName = "PSUsePSCredentialType" $directory = Split-Path -Parent $MyInvocation.MyCommand.Path $violations = Invoke-ScriptAnalyzer $directory\PSCredentialType.ps1 | Where-Object {$_.RuleName -eq $violationName} @@ -12,7 +12,7 @@ Describe "PSCredentialType" { } It "has the correct description message" { - $violations[0].Message | Should Match $violationMessage + $violations[0].Message | Should Be $violationMessage } } diff --git a/Tests/Rules/PSCredentialTypeNoViolations.ps1 b/Tests/Rules/PSCredentialTypeNoViolations.ps1 index 7b8f09bc0..6f4f375ad 100644 --- a/Tests/Rules/PSCredentialTypeNoViolations.ps1 +++ b/Tests/Rules/PSCredentialTypeNoViolations.ps1 @@ -10,7 +10,7 @@ ValueFromPipelineByPropertyName=$true, Position=0)] [pscredential] - [System.Management.Automation.CredentialAttribute()] + [System.Management.Automation.Credential()] $Credential ) } \ No newline at end of file