diff --git a/.ci/releaseBuild.yml b/.ci/releaseBuild.yml new file mode 100644 index 000000000..ac5cf74c7 --- /dev/null +++ b/.ci/releaseBuild.yml @@ -0,0 +1,199 @@ +# The name of the build that will be seen in mscodehub +name: PSSA-Release-$(Build.BuildId) +# how is the build triggered +# since this is a release build, no trigger as it's a manual release +trigger: none + +pr: + branches: + include: + - master + - release* + +# variables to set in the build environment +variables: + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + POWERSHELL_TELEMETRY_OPTOUT: 1 + +# since this build relies on templates, we need access to those +# This needs a service connection in the build to work +# the *name* of the service connection must be the same as the endpoint +resources: + repositories: + - repository: ComplianceRepo + type: github + endpoint: ComplianceGHRepo + name: PowerShell/compliance + # this can be any branch of your choosing + ref: master + +# the stages in this build. There are 2 +# the assumption for script analyzer is that test is done as part of +# CI so we needn't do it here +stages: +- stage: Build + displayName: Build + pool: + name: Package ES CodeHub Lab E + jobs: + - job: Build_Job + displayName: Build Microsoft.PowerShell.ScriptAnalyzer + # note the variable reference to ESRP. + # this must be created in Project -> Pipelines -> Library -> VariableGroups + # where it describes the link to the SigningServer + variables: + - group: ESRP + steps: + - checkout: self + + # the steps for building the module go here + - pwsh: | + Set-Location "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA" + try { ./build.ps1 -Configuration Release -All } catch { throw $_ } + displayName: Execute build + + # these are setting vso variables which will be persisted between stages + - pwsh: | + $signSrcPath = "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA/out" + # Set signing src path variable + $vstsCommandString = "vso[task.setvariable variable=signSrcPath]${signSrcPath}" + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + + $signOutStep1 = "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA/Step1" + $null = New-Item -ItemType Directory -Path $signOutStep1 + # Set signing out path variable + $vstsCommandString = "vso[task.setvariable variable=signOutStep1]${signOutStep1}" + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + + $signOutPath = "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA/signed" + $null = New-Item -ItemType Directory -Path $signOutPath + # Set signing out path variable + $vstsCommandString = "vso[task.setvariable variable=signOutPath]${signOutPath}" + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + + # Set path variable for guardian codesign validation + $vstsCommandString = "vso[task.setvariable variable=GDN_CODESIGN_TARGETDIRECTORY]${signOutPath}" + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + + # Get version and create a variable + $moduleData = Import-PowerShellDataFile "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA/Engine/PSScriptAnalyzer.psd1" + $moduleVersion = $moduleData.ModuleVersion + $vstsCommandString = "vso[task.setvariable variable=moduleVersion]${moduleVersion}" + Write-Host "sending $vstsCommandString" + Write-Host "##$vstsCommandString" + + + displayName: Setup variables for signing + + # checkout the Compliance repository so it can be used to do the actual signing + - checkout: ComplianceRepo + + # in script analyzer, we must sign with 2 different certs + # the normal cert for MS created items and the 3rd party cert + # this the MS authored step + # Because this needs 2 certs, we do it in 2 steps. + # the first step signs the binaries and puts them in a staging directory which + # will then be used for the second step. + - template: EsrpSign.yml@ComplianceRepo + parameters: + # the folder which contains the binaries to sign + buildOutputPath: $(signSrcPath) + # the location to put the signed output + signOutputPath: $(signOutStep1) + # the certificate ID to use + certificateId: "CP-230012" + # use minimatch because we need to exclude the NewtonSoft assembly + useMinimatch: true + # the file pattern to use - newtonSoft is excluded + pattern: | + **\*.psd1 + **\*.psm1 + **\*.ps1xml + **\Microsoft*.dll + + # this is the second step of the signing. + # note that the buildOutputPath (where we get the files to sign) + # is the same as the signOutputPath in the previous step + # at the end of this step we will have all the files signed that should be + # signOutPath is the location which contains the files we will use to make the module + - template: EsrpSign.yml@ComplianceRepo + parameters: + # the folder which contains the binaries to sign + buildOutputPath: $(signOutStep1) + # the location to put the signed output + signOutputPath: $(signOutPath) + # the certificate ID to use + # we'll need to change this to the 3rd party cert id + certificateId: "CP-231522" + # the file pattern to use - only sign newtonsoft + pattern: 'Newtonsoft*.dll' + + # now create the nupkg which we will use to publish the module + # to the powershell gallery (not part of this yaml) + - pwsh: | + Set-Location "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA" + ./build -BuildNupkg -signed + displayName: Create nupkg for publishing + + # finally publish the parts of the build which will be used in the next stages + # if it's not published, the subsequent stages will not be able to access it. + # This is the build directory (it contains all of the dll/pdb files) + - publish: "$(Build.SourcesDirectory)/OSS_Microsoft_PSSA" + artifact: build + displayName: publish build directory + + # export the nupkg only which will be used in the release pipeline + - publish: "$(signOutPath)/PSScriptAnalyzer.$(moduleVersion).nupkg" + artifact: nupkg + displayName: Publish module nupkg + +# Now on to the compliance stage +- stage: compliance + displayName: Compliance + dependsOn: Build + jobs: + - job: Compliance_Job + pool: + name: Package ES CodeHub Lab E + steps: + - checkout: self + - checkout: ComplianceRepo + - download: current + artifact: build + + # use the templates in the compliance repo + # since script analyzer has modules, we're using the assembly-module-compliance template + # if you don't have assemblies, you should use script-module-compliance template + - template: assembly-module-compliance.yml@ComplianceRepo + parameters: + # component-governance - the path to sources + sourceScanPath: '$(Build.SourcesDirectory)/OSS_Microsoft_PSSA' + # binskim - this isn't recursive, so you need the path to the assemblies + AnalyzeTarget: '$(Pipeline.Workspace)\build\bin\PSV7Release\netcoreapp3.1\*.dll' + # credscan - scan the repo for credentials + # you can suppress some files with this. + suppressionsFile: '$(Build.SourcesDirectory)/OSS_Microsoft_PSSA/tools/ReleaseBuild/CredScan.Suppressions.json' + # TermCheck + optionsRulesDBPath: '' + optionsFTPath: '' + # tsa-upload + # the compliance scanning must be uploaded, which you need to request + codeBaseName: 'PSSA_202004' + # selections + APIScan: false # set to false when not using Windows APIs. + +#- template: template/publish.yml +# parameters: +# stageName: AzArtifactsFeed +# environmentName: +# feedCredential: + +#- template: template/publish.yml +# parameters: +# stageName: NuGet +# environmentName: PSMarkdownRenderNuGetApproval +# feedCredential: NugetOrgPush diff --git a/Engine/Engine.csproj b/Engine/Engine.csproj index 64a07032e..debb7c4ef 100644 --- a/Engine/Engine.csproj +++ b/Engine/Engine.csproj @@ -1,10 +1,10 @@  - 1.19.1 + 1.20.0 netcoreapp3.1;net452 Microsoft.Windows.PowerShell.ScriptAnalyzer - 1.19.1 + 1.20.0 Engine Microsoft.Windows.PowerShell.ScriptAnalyzer diff --git a/Engine/PSScriptAnalyzer.psd1 b/Engine/PSScriptAnalyzer.psd1 index 423f8e42b..16eeb90ae 100644 --- a/Engine/PSScriptAnalyzer.psd1 +++ b/Engine/PSScriptAnalyzer.psd1 @@ -11,7 +11,7 @@ Author = 'Microsoft Corporation' RootModule = 'PSScriptAnalyzer.psm1' # Version number of this module. -ModuleVersion = '1.19.1' +ModuleVersion = '1.20.0' # ID used to uniquely identify this module GUID = 'd6245802-193d-4068-a631-8863a4342a18' diff --git a/PSCompatibilityCollector/Microsoft.PowerShell.CrossCompatibility/Microsoft.PowerShell.CrossCompatibility.csproj b/PSCompatibilityCollector/Microsoft.PowerShell.CrossCompatibility/Microsoft.PowerShell.CrossCompatibility.csproj index 40e03f2ab..6cbdf655d 100644 --- a/PSCompatibilityCollector/Microsoft.PowerShell.CrossCompatibility/Microsoft.PowerShell.CrossCompatibility.csproj +++ b/PSCompatibilityCollector/Microsoft.PowerShell.CrossCompatibility/Microsoft.PowerShell.CrossCompatibility.csproj @@ -1,9 +1,9 @@  - 1.19.1 + 1.20.0 netstandard2.0;net452 - 1.19.1 + 1.20.0 diff --git a/RuleDocumentation/AvoidUsingCmdletAliases.md b/RuleDocumentation/AvoidUsingCmdletAliases.md index a19cc32ef..46fcd2f2a 100644 --- a/RuleDocumentation/AvoidUsingCmdletAliases.md +++ b/RuleDocumentation/AvoidUsingCmdletAliases.md @@ -28,7 +28,7 @@ To prevent `PSScriptAnalyzer` from flagging your preferred aliases, create an al @{ 'Rules' = @{ 'PSAvoidUsingCmdletAliases' = @{ - 'Whitelist' = @('cd') + 'allowlist' = @('cd') } } } diff --git a/Rules/Rules.csproj b/Rules/Rules.csproj index 2fcf8f225..157f4467d 100644 --- a/Rules/Rules.csproj +++ b/Rules/Rules.csproj @@ -1,10 +1,10 @@  - 1.19.1 + 1.20.0 netcoreapp3.1;net452 Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules - 1.19.1 + 1.20.0 Rules Microsoft.Windows.PowerShell.ScriptAnalyzer diff --git a/Tests/Engine/Settings.tests.ps1 b/Tests/Engine/Settings.tests.ps1 index e0845425c..2e95bdd04 100644 --- a/Tests/Engine/Settings.tests.ps1 +++ b/Tests/Engine/Settings.tests.ps1 @@ -109,7 +109,7 @@ Describe "Settings Class" { $settingsHashtable = @{ Rules = @{ PSAvoidUsingCmdletAliases = @{ - WhiteList = @("cd", "cp") + allowlist = @("cd", "cp") } } } @@ -117,15 +117,15 @@ Describe "Settings Class" { } It "Should return the rule arguments" { - $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["WhiteList"].Count | Should -Be 2 - $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["WhiteList"][0] | Should -Be "cd" - $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["WhiteList"][1] | Should -Be "cp" + $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["allowlist"].Count | Should -Be 2 + $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["allowlist"][0] | Should -Be "cd" + $settings.RuleArguments["PSAvoidUsingCmdletAliases"]["allowlist"][1] | Should -Be "cp" } It "Should Be case insensitive" { - $settings.RuleArguments["psAvoidUsingCmdletAliases"]["whiteList"].Count | Should -Be 2 - $settings.RuleArguments["psAvoidUsingCmdletAliases"]["whiteList"][0] | Should -Be "cd" - $settings.RuleArguments["psAvoidUsingCmdletAliases"]["whiteList"][1] | Should -Be "cp" + $settings.RuleArguments["psAvoidUsingCmdletAliases"]["allowlist"].Count | Should -Be 2 + $settings.RuleArguments["psAvoidUsingCmdletAliases"]["allowlist"][0] | Should -Be "cd" + $settings.RuleArguments["psAvoidUsingCmdletAliases"]["allowlist"][1] | Should -Be "cp" } } diff --git a/Tests/Engine/SettingsTest/Issue828/PSScriptAnalyzerSettings.psd1 b/Tests/Engine/SettingsTest/Issue828/PSScriptAnalyzerSettings.psd1 index 0fd0abff9..bc9c33a89 100644 --- a/Tests/Engine/SettingsTest/Issue828/PSScriptAnalyzerSettings.psd1 +++ b/Tests/Engine/SettingsTest/Issue828/PSScriptAnalyzerSettings.psd1 @@ -15,7 +15,7 @@ } PSAvoidUsingCmdletAliases = @{ # only allowlist verbs from *-Object cmdlets - Whitelist = @( + allowlist = @( '%', '?', 'compare', @@ -60,4 +60,4 @@ CheckSeparator = $true } } -} \ No newline at end of file +} diff --git a/Tests/Engine/SettingsTest/Project1/ExplicitSettings.psd1 b/Tests/Engine/SettingsTest/Project1/ExplicitSettings.psd1 index 3e7c8caa3..29fb7bce2 100644 --- a/Tests/Engine/SettingsTest/Project1/ExplicitSettings.psd1 +++ b/Tests/Engine/SettingsTest/Project1/ExplicitSettings.psd1 @@ -3,7 +3,7 @@ "ExcludeRules" = @("PSShouldProcess", "PSAvoidUsingWMICmdlet", "PSUseCmdletCorrectly") "rules" = @{ PSAvoidUsingCmdletAliases = @{ - WhiteList = @("cd", "cp") + allowlist = @("cd", "cp") } PSUseConsistentIndentation = @{ diff --git a/Tests/Rules/AvoidUsingAlias.tests.ps1 b/Tests/Rules/AvoidUsingAlias.tests.ps1 index ca16cf6a8..d1e29a4a1 100644 --- a/Tests/Rules/AvoidUsingAlias.tests.ps1 +++ b/Tests/Rules/AvoidUsingAlias.tests.ps1 @@ -73,7 +73,7 @@ Configuration MyDscConfiguration { $settings = @{ 'Rules' = @{ 'PSAvoidUsingCmdletAliases' = @{ - 'Whitelist' = @('cd') + 'allowlist' = @('cd') } } } @@ -83,7 +83,7 @@ Configuration MyDscConfiguration { $settings = @{ 'Rules' = @{ 'PSAvoidUsingCmdletAliases' = @{ - 'Whitelist' = @('cd') + 'allowlist' = @('cd') } } } diff --git a/Tests/Rules/TestSettings/AvoidAliasSettings.psd1 b/Tests/Rules/TestSettings/AvoidAliasSettings.psd1 index e5a4cb1af..ada212196 100644 --- a/Tests/Rules/TestSettings/AvoidAliasSettings.psd1 +++ b/Tests/Rules/TestSettings/AvoidAliasSettings.psd1 @@ -1,7 +1,7 @@ @{ 'Rules' = @{ 'PSAvoidUsingCmdletAliases' = @{ - 'Whitelist' = @('cd') + 'allowlist' = @('cd') } } -} \ No newline at end of file +} diff --git a/build.ps1 b/build.ps1 index 1f4687b84..4f537214a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -37,7 +37,13 @@ param( [switch] $Bootstrap, [Parameter(ParameterSetName='BuildAll')] - [switch] $Catalog + [switch] $Catalog, + + [Parameter(ParameterSetName='Package')] + [switch] $BuildNupkg, + + [Parameter(ParameterSetName='Package')] + [switch] $Signed ) @@ -85,6 +91,9 @@ END { Install-DotNet return } + "Package" { + Start-CreatePackage -signed:$Signed + } "Test" { Test-ScriptAnalyzer -InProcess:$InProcess return diff --git a/build.psm1 b/build.psm1 index 8a61674ee..d7a7347f3 100644 --- a/build.psm1 +++ b/build.psm1 @@ -708,7 +708,13 @@ function Get-DotnetExe Write-Warning "Could not find dotnet executable" return [String]::Empty } -$script:DotnetExe = Get-DotnetExe + +try { + $script:DotnetExe = Get-DotnetExe +} +catch { + Write-Warning "Could not find dotnet executable" +} # Copies the built PSCompatibilityCollector module to the output destination for PSSA function Copy-CrossCompatibilityModule @@ -756,3 +762,27 @@ function Copy-CrossCompatibilityModule } } } + +# creates the nuget package which can be used for publishing to the gallery +function Start-CreatePackage +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleCommands', '')] + param ( [switch]$signed ) + try { + if ( $signed ) { + $buildRoot = "signed" + } + else { + $buildRoot = "out" + } + $repoName = [guid]::NewGuid().ToString() + $nupkgDir = Join-Path $PSScriptRoot $buildRoot + $null = Register-PSRepository -Name $repoName -InstallationPolicy Trusted -SourceLocation $nupkgDir + Push-Location $nupkgDir + Publish-Module -Path $PWD/PSScriptAnalyzer -Repository $repoName + } + finally { + Pop-Location + Unregister-PSRepository -Name $repoName + } +} diff --git a/tools/releaseBuild/CredScan.Suppressions.json b/tools/releaseBuild/CredScan.Suppressions.json index 53b49888f..0a0e5db11 100644 --- a/tools/releaseBuild/CredScan.Suppressions.json +++ b/tools/releaseBuild/CredScan.Suppressions.json @@ -1,6 +1,8 @@ { "tool": "Credential Scanner", "suppressions": [ + { "file": "\\README.md", + "_justification": "The file refers to passwords but has no actual passwords" }, { "file": "\\Engine\\Settings\\desktop-4.0-windows.json", "_justification": "The file contains the list of all parameters of a cmdlet but no passwords are actually present." }, { "file": "\\Engine\\Settings\\desktop-3.0-windows.json",