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