@@ -10,104 +10,126 @@ runs:
1010 shell : pwsh
1111 run : |
1212 $ErrorActionPreference = "Stop";
13-
14- foreach($project in Get-ChildItem -Path . -Filter *.??proj -Recurse -Force) {
15-
16- $xml = [xml](Get-Content -Path $project)
17- if (-not $xml.Project.xmlns) {
18- dotnet add $project package SecurityCodeScan.VS2019
19- }
20- else {
21- $packageId = "SecurityCodeScan.VS2019"
22- $scs2019packages = Invoke-RestMethod -Uri "https://api-v2v3search-0.nuget.org/query?q=packageid:SecurityCodeScan.VS2019&top=true"
23- $packageVersion = $scs2019packages.data.versions | Sort-Object -Property version -Descending | Select-Object -First 1
24- $packageVersion = $packageVersion.version
25-
26- $packages = $project | Split-Path -parent
27- $packages = Join-Path $packages "packages.config"
28-
29- $id = get-random
30- $code = @"
31- using System;
32- using System.Runtime.Versioning;
33- using System.Text.RegularExpressions;
34- using System.Xml;
35-
36- public class Program$id
37- {
38- public static void Main(){
39- var projXml = new XmlDocument();
40- projXml.Load(@"$project");
41-
42- var xmlNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";
43- var nsmgr = new XmlNamespaceManager(projXml.NameTable);
44- nsmgr.AddNamespace("x", xmlNamespace);
45-
46- XmlNode itemGroupNode = projXml.CreateNode(XmlNodeType.Element, "ItemGroup", xmlNamespace);
47- XmlNode analyzerNode = projXml.CreateNode(XmlNodeType.Element, "Analyzer", xmlNamespace);
48- XmlAttribute includeAttribute = projXml.CreateAttribute("Include");
49- includeAttribute.Value = $@"..\packages\$packageId.$packageVersion\analyzers\dotnet\SecurityCodeScan.VS2019.dll";
50- analyzerNode.Attributes.Append(includeAttribute);
51- itemGroupNode.AppendChild(analyzerNode);
52- projXml.SelectSingleNode("//x:Project", nsmgr).AppendChild(itemGroupNode);
53- projXml.Save(@"$project");
54-
55- XmlNode targetFrameworkNode = projXml.SelectSingleNode("//x:TargetFrameworkVersion", nsmgr);
56- var targetFwAttribute = new TargetFrameworkAttribute($".NETFramework, Version={targetFrameworkNode.InnerXml}");
57- Regex p = new Regex(@"\d+(\.\d+)+");
58- Match m = p.Match(targetFwAttribute.FrameworkName);
59- Version targetFwVersion = Version.Parse(m.Value);
60-
61- var packagesXml = new XmlDocument();
62- packagesXml.Load(@"$packages");
63-
64- var packagesNode = packagesXml.SelectSingleNode("//packages");
65-
66- XmlNode packageNode = packagesXml.CreateElement("package");
67-
68- XmlAttribute idAttribute = packagesXml.CreateAttribute("id");
69- idAttribute.Value = "$packageId";
70- packageNode.Attributes.Append(idAttribute);
71-
72- XmlAttribute versionAttribute = packagesXml.CreateAttribute("version");
73- versionAttribute.Value = "$packageVersion";
74- packageNode.Attributes.Append(versionAttribute);
75-
76- XmlAttribute targetFrameworkAttribute = packagesXml.CreateAttribute("targetFramework");
77- targetFrameworkAttribute.Value = $"net{targetFwVersion.ToString().Replace(".", "")}";
78- packageNode.Attributes.Append(targetFrameworkAttribute);
79-
80- XmlAttribute developmentDependencyAttribute = packagesXml.CreateAttribute("developmentDependency");
81- developmentDependencyAttribute.Value = "true";
82- packageNode.Attributes.Append(developmentDependencyAttribute);
83-
84- packagesNode.AppendChild(packageNode);
85- packagesXml.Save(@"$packages");
13+ [string]$SecurityCodeScanPackageName = 'SecurityCodeScan.VS2019'
14+ [string]$SecurityCodeScanPackagePath = $null
15+
16+ # get the latest security code scan package version
17+ $scs2019packages = Invoke-RestMethod -Uri "https://api-v2v3search-0.nuget.org/query?q=packageid:SecurityCodeScan.VS2019&top=true"
18+ $SecurityCodeScanPackageVersion = $scs2019packages.data.versions | Sort-Object -Property version -Descending | Select-Object -First 1 | Select-Object -Property version
19+
20+ foreach ($projectFile in Get-ChildItem -Path . -Include *.csproj, *.vbproj -File -Recurse -Force) {
21+
22+ $project = [xml](Get-Content -LiteralPath $projectFile.FullName -Raw)
23+ $propertyGroup = $project.CreateElement('PropertyGroup', $project.Project.NamespaceURI)
24+
25+ # redirect all warnings to analysis.sarif file
26+ $errorLog = $project.CreateElement('ErrorLog', $project.Project.NamespaceURI)
27+ $errorLog.InnerText = 'analysis.sarif'
28+ $propertyGroup.AppendChild($errorLog) | Out-Null
29+
30+ # add AdditionalFileItemNames to enable scanning of web.config
31+ # should we check if the AdditionalFileItemNames already exists?
32+ $additionalFileItemNames = $project.CreateElement("AdditionalFileItemNames", $project.Project.NamespaceURI)
33+ $additionalFileItemNames.InnerText = '$(AdditionalFileItemNames);Content'
34+ $propertyGroup.AppendChild($additionalFileItemNames) | Out-Null
35+
36+ $project.Project.AppendChild($propertyGroup) | Out-Null
37+ $project.Save($projectFile.FullName)
38+
39+ $packagesConfigFile = $projectFile.Directory.GetFileSystemInfos('packages.config')
40+
41+ # if the project is new .NET Core style or the old one, but uses PackageReference
42+ if ($project.Project.Sdk -or ($project.Project.ItemGroup.PackageReference | Where-Object { $_ }) -or (-not $packagesConfigFile.Exists)) {
43+ # delete existing SecurityCodeScan PackageReference entities
44+ $project.Project.ItemGroup.PackageReference |
45+ Where-Object Include -like 'SecurityCodeScan*' |
46+ ForEach-Object { $_.SelectSingleNode('..').RemoveChild($_) | Out-Null }
47+
48+ $packageReference = $project.CreateElement('PackageReference')
49+ $packageReferenceInclude = $project.CreateAttribute('Include')
50+ $packageReferenceInclude.Value = $SecurityCodeScanPackageName
51+ $packageReference.Attributes.Append($packageReferenceInclude) | Out-Null
52+ $packageReferenceVersion = $project.CreateAttribute('Version')
53+ $packageReferenceVersion.Value = $SecurityCodeScanPackageVersion
54+ $packageReference.Attributes.Append($packageReferenceVersion) | Out-Null
55+ $packageReferencePrivateAssets = $project.CreateAttribute('PrivateAssets')
56+ $packageReferencePrivateAssets.Value = 'All'
57+ $packageReference.Attributes.Append($packageReferencePrivateAssets) | Out-Null
58+ $packageReferenceIncludeAssets = $project.CreateAttribute('IncludeAssets')
59+ $packageReferenceIncludeAssets.Value = 'runtime; build; native; contentfiles; analyzers; buildtransitive'
60+ $packageReference.Attributes.Append($packageReferenceIncludeAssets) | Out-Null
61+ $itemGroup = $project.CreateElement('ItemGroup')
62+ $itemGroup.AppendChild($packageReference) | Out-Null
63+ $project.Project.AppendChild($itemGroup) | Out-Null
64+
65+ # create RestoreProjectStyle element
66+ if (-not $project.Project.Sdk) {
67+ $restoreProjectStyle = $project.CreateElement('RestoreProjectStyle')
68+ $restoreProjectStyle.InnerText = 'PackageReference'
69+ $propertyGroup = $project.CreateElement('PropertyGroup')
70+ $propertyGroup.AppendChild($restoreProjectStyle) | Out-Null
71+ $project.Project.AppendChild($propertyGroup) | Out-Null
72+ }
73+
74+ $project.Save($projectFile.FullName)
8675 }
87- }
88- "@
89-
90- Add-Type -TypeDefinition $code -Language CSharp
91- Invoke-Expression "[Program$id]::Main()"
76+ else { # Old style Full DotNet Framework project with packages.config
77+
78+ # create or get the full path to the solution path directory
79+ if (-not $SecurityCodeScanPackagePath) {
80+ if (-not (Test-Path packages -PathType Container)) {
81+ $SecurityCodeScanPackagePath = (New-Item -Name packages -ItemType Directory).FullName
82+ }
83+ else {
84+ $SecurityCodeScanPackagePath = (Get-Item -Path packages).FullName
85+ }
86+ }
87+
88+ # delete existing SecurityCodeScan analyzer entities
89+ $project.Project.ItemGroup.Analyzer |
90+ Where-Object Include -like '*SecurityCodeScan*' |
91+ ForEach-Object { $_.SelectSingleNode('..').RemoveChild($_) | Out-Null }
92+
93+ # create RestoreProjectStyle element
94+ $restoreProjectStyle = $project.CreateElement('RestoreProjectStyle', $project.Project.NamespaceURI)
95+ $restoreProjectStyle.InnerText = 'PackagesConfig'
96+ $propertyGroup = $project.CreateElement('PropertyGroup', $project.Project.NamespaceURI)
97+ $propertyGroup.AppendChild($restoreProjectStyle) | Out-Null
98+ $project.Project.AppendChild($propertyGroup) | Out-Null
99+
100+ # create Analyzer element
101+ $itemGroup = $project.CreateElement('ItemGroup', $project.Project.NamespaceURI)
102+ $analyzer = $project.CreateElement('Analyzer', $project.Project.NamespaceURI)
103+ $analyzerInclude = $project.CreateAttribute('Include')
104+ # since the changes to the project will be discarded it is ok to set a Full path to SecurityCodeScanPackagePath
105+ $analyzerInclude.Value = Join-Path -Path $SecurityCodeScanPackagePath -ChildPath "$($SecurityCodeScanPackageName).$($SecurityCodeScanPackageVersion)\analyzers\dotnet\SecurityCodeScan.VS2019.dll"
106+ $analyzer.Attributes.Append($analyzerInclude) | Out-Null
107+ $itemGroup.AppendChild($analyzer) | Out-Null
108+ $project.Project.AppendChild($itemGroup) | Out-Null
109+
110+ $project.Save($projectFile.FullName)
111+
112+ $packagesConfig = [xml](Get-Content -LiteralPath $packagesConfigFile.FullName -Raw)
113+
114+ # delete existing SecurityCodeScan package entities
115+ $packagesConfig.packages.package |
116+ Where-Object id -like '*SecurityCodeScan*' |
117+ ForEach-Object { $_.SelectSingleNode('..').RemoveChild($_) | Out-Null }
118+
119+ # create a SecurityCodeScan package entity
120+ $package = $packagesConfig.CreateElement('package')
121+ $packageId = $packagesConfig.CreateAttribute('id')
122+ $packageId.Value = $SecurityCodeScanPackageName
123+ $package.Attributes.Append($packageId) | Out-Null
124+ $packageVersion = $packagesConfig.CreateAttribute('version')
125+ $packageVersion.Value = $SecurityCodeScanPackageVersion
126+ $package.Attributes.Append($packageVersion) | Out-Null
127+ $packageDevelopmentDependency = $packagesConfig.CreateAttribute('developmentDependency')
128+ $packageDevelopmentDependency.Value = 'true'
129+ $package.Attributes.Append($packageDevelopmentDependency) | Out-Null
130+
131+ $packagesConfig.packages.AppendChild($package) | Out-Null
132+
133+ $packagesConfig.Save($packagesConfigFile.FullName)
92134 }
93-
94- $xml = [xml](Get-Content -Path $project)
95- if ($xml.Project.xmlns) {
96- $nsmgr = New-Object System.Xml.XmlNamespaceManager $xml.NameTable
97- $nsmgr.AddNamespace('x','http://schemas.microsoft.com/developer/msbuild/2003')
98- $x = 'x:'
99- }
100- $propertyGroups = $xml.SelectNodes("//${x}Project/${x}PropertyGroup", $nsmgr)
101-
102- $errorLog = $xml.CreateElement("ErrorLog", $xml.Project.NamespaceURI)
103- $errorLog.set_InnerText("analysis.sarif")
104- $propertyGroups[0].AppendChild($errorLog)
105-
106- if (-not $propertyGroups[0].AdditionalFileItemNames) {
107- $additionalFileItemNamesElt = $xml.CreateElement("AdditionalFileItemNames", $xml.Project.NamespaceURI)
108- $additionalFileItemNamesElt.set_InnerText('$(AdditionalFileItemNames);Content')
109- $propertyGroups[0].AppendChild($additionalFileItemNamesElt)
110- }
111-
112- $xml.Save($project)
113135 }
0 commit comments