Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 5fbb374

Browse files
authored
Scan and Sign validator, orchestrator side (#440)
* Started shared scan and sign project. * Added new project to a build script. * ScanAndSignMessageSerializer * Added scan and sign validator name. * Missed merge conflict * No more autodetect requests. * Updated to latest NuGet.Services.Validation * Updated nuspec * Scan processor * Configuration update * DI updates * Tests * usings * Less usings * Sign target for the new projcet * Missing copyright header * Fixed merge
1 parent 2953a8f commit 5fbb374

21 files changed

Lines changed: 858 additions & 3 deletions

NuGet.Jobs.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validation.PackageSigning.R
119119
EndProject
120120
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validation.PackageSigning.RevalidateCertificate.Tests", "tests\Validation.PackageSigning.RevalidateCertificate.Tests\Validation.PackageSigning.RevalidateCertificate.Tests.csproj", "{64095857-E9E3-4D9C-8769-7E558CD757CB}"
121121
EndProject
122+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validation.ScanAndSign.Core", "src\Validation.ScanAndSign.Core\Validation.ScanAndSign.Core.csproj", "{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE}"
123+
EndProject
122124
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Stats.AggregateCdnDownloadsInGallery", "tests\Tests.Stats.AggregateCdnDownloadsInGallery\Tests.Stats.AggregateCdnDownloadsInGallery.csproj", "{136411AF-B9FA-438D-B790-9FB78A5F7F54}"
123125
EndProject
126+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validation.PackageSigning.ScanAndSign.Tests", "tests\Validation.PackageSigning.ScanAndSign.Tests\Validation.PackageSigning.ScanAndSign.Tests.csproj", "{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687}"
127+
EndProject
124128
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Monitoring", "Monitoring", "{814F9B31-4AF3-46CC-AD61-CEB40F47083A}"
125129
EndProject
126130
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Monitoring.PackageLag", "src\PackageLagMonitor\Monitoring.PackageLag.csproj", "{B5147169-E941-4CF8-9FCD-1C123ACD3149}"
@@ -313,10 +317,18 @@ Global
313317
{64095857-E9E3-4D9C-8769-7E558CD757CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
314318
{64095857-E9E3-4D9C-8769-7E558CD757CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
315319
{64095857-E9E3-4D9C-8769-7E558CD757CB}.Release|Any CPU.Build.0 = Release|Any CPU
320+
{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
321+
{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
322+
{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
323+
{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE}.Release|Any CPU.Build.0 = Release|Any CPU
316324
{136411AF-B9FA-438D-B790-9FB78A5F7F54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
317325
{136411AF-B9FA-438D-B790-9FB78A5F7F54}.Debug|Any CPU.Build.0 = Debug|Any CPU
318326
{136411AF-B9FA-438D-B790-9FB78A5F7F54}.Release|Any CPU.ActiveCfg = Release|Any CPU
319327
{136411AF-B9FA-438D-B790-9FB78A5F7F54}.Release|Any CPU.Build.0 = Release|Any CPU
328+
{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
329+
{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687}.Debug|Any CPU.Build.0 = Debug|Any CPU
330+
{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687}.Release|Any CPU.ActiveCfg = Release|Any CPU
331+
{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687}.Release|Any CPU.Build.0 = Release|Any CPU
320332
{B5147169-E941-4CF8-9FCD-1C123ACD3149}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
321333
{B5147169-E941-4CF8-9FCD-1C123ACD3149}.Debug|Any CPU.Build.0 = Debug|Any CPU
322334
{B5147169-E941-4CF8-9FCD-1C123ACD3149}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -371,7 +383,9 @@ Global
371383
{26435822-8938-48C9-96FD-0DCCF8F7CE00} = {6A776396-02B1-475D-A104-26940ADB04AB}
372384
{EA32E1E5-7E7D-44E6-B496-43E1FEDE9400} = {678D7B14-F8BC-4193-99AF-2EE8AA390A02}
373385
{64095857-E9E3-4D9C-8769-7E558CD757CB} = {6A776396-02B1-475D-A104-26940ADB04AB}
386+
{DFAC2769-4B67-4FBC-AD60-D93A39DD45AE} = {678D7B14-F8BC-4193-99AF-2EE8AA390A02}
374387
{136411AF-B9FA-438D-B790-9FB78A5F7F54} = {6A776396-02B1-475D-A104-26940ADB04AB}
388+
{CAE45AC9-F11B-4215-9D1A-C98BC0F1F687} = {6A776396-02B1-475D-A104-26940ADB04AB}
375389
{B5147169-E941-4CF8-9FCD-1C123ACD3149} = {814F9B31-4AF3-46CC-AD61-CEB40F47083A}
376390
EndGlobalSection
377391
GlobalSection(ExtensibilityGlobals) = postSolution

build.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Invoke-BuildStep 'Set version metadata in AssemblyInfo.cs' { `
112112
"$PSScriptRoot\src\Validation.PackageSigning.RevalidateCertificate\Properties\AssemblyInfo.g.cs",
113113
"$PSScriptRoot\src\NuGet.Jobs.Common\Properties\AssemblyInfo.g.cs",
114114
"$PSScriptRoot\src\Validation.Common.Job\Properties\AssemblyInfo.g.cs",
115+
"$PSScriptRoot\src\Validation.ScanAndSign.Core\Properties\AssemblyInfo.g.cs",
115116
"$PSScriptRoot\src\PackageLagMonitor\Properties\AssemblyInfo.g.cs"
116117

117118
$versionMetadata | ForEach-Object {
@@ -144,7 +145,8 @@ Invoke-BuildStep 'Creating artifacts' {
144145
# don't need to be shared, hence no need for symbols for them
145146
$ProjectsWithSymbols =
146147
"src/NuGet.Jobs.Common/NuGet.Jobs.Common.csproj",
147-
"src/Validation.Common.Job/Validation.Common.Job.csproj"
148+
"src/Validation.Common.Job/Validation.Common.Job.csproj",
149+
"src/Validation.ScanAndSign.Core/Validation.ScanAndSign.Core.csproj"
148150

149151
$Projects = `
150152
"src/Stats.CollectAzureCdnLogs/Stats.CollectAzureCdnLogs.csproj", `

src/NuGet.Services.Validation.Orchestrator/Job.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
using NuGet.Jobs.Validation.Common;
2525
using NuGet.Jobs.Validation.PackageSigning.Messages;
2626
using NuGet.Jobs.Validation.PackageSigning.Storage;
27+
using NuGet.Jobs.Validation.ScanAndSign;
2728
using NuGet.Jobs.Validation.Storage;
2829
using NuGet.Services.Configuration;
2930
using NuGet.Services.KeyVault;
3031
using NuGet.Services.Logging;
3132
using NuGet.Services.ServiceBus;
33+
using NuGet.Services.Validation.Orchestrator.PackageSigning.ScanAndSign;
3234
using NuGet.Services.Validation.Orchestrator.Telemetry;
3335
using NuGet.Services.Validation.PackageSigning.ProcessSignature;
3436
using NuGet.Services.Validation.PackageSigning.ValidateCertificate;
@@ -47,6 +49,7 @@ public class Job : JobBase
4749
private const string VcsSectionName = "Vcs";
4850
private const string PackageSigningSectionName = "PackageSigning";
4951
private const string PackageCertificatesSectionName = "PackageCertificates";
52+
private const string ScanAndSignSectionName = "ScanAndSign";
5053
private const string RunnerConfigurationSectionName = "RunnerConfiguration";
5154
private const string GalleryDbConfigurationSectionName = "GalleryDb";
5255
private const string ValidationDbConfigurationSectionName = "ValidationDb";
@@ -59,6 +62,7 @@ public class Job : JobBase
5962
private const string PackageVerificationTopicClientBindingKey = "PackageVerificationTopicClient";
6063
private const string PackageSignatureBindingKey = PackageSigningSectionName;
6164
private const string PackageCertificatesBindingKey = PackageCertificatesSectionName;
65+
private const string ScanAndSignBindingKey = ScanAndSignSectionName;
6266
private const string ValidationStorageBindingKey = "ValidationStorage";
6367
private const string OrchestratorBindingKey = "Orchestrator";
6468

@@ -154,6 +158,7 @@ private void ConfigureJobServices(IServiceCollection services, IConfigurationRoo
154158
services.Configure<ServiceBusConfiguration>(configurationRoot.GetSection(ServiceBusConfigurationSectionName));
155159
services.Configure<SmtpConfiguration>(configurationRoot.GetSection(SmtpConfigurationSectionName));
156160
services.Configure<EmailConfiguration>(configurationRoot.GetSection(EmailConfigurationSectionName));
161+
services.Configure<ScanAndSignConfiguration>(configurationRoot.GetSection(ScanAndSignSectionName));
157162

158163
services.AddTransient<ConfigurationValidator>();
159164
services.AddTransient<OrchestrationRunner>();
@@ -204,6 +209,7 @@ private void ConfigureJobServices(IServiceCollection services, IConfigurationRoo
204209
services.AddTransient<IValidationSetProcessor, ValidationSetProcessor>();
205210
services.AddTransient<IBrokeredMessageSerializer<SignatureValidationMessage>, SignatureValidationMessageSerializer>();
206211
services.AddTransient<IBrokeredMessageSerializer<CertificateValidationMessage>, CertificateValidationMessageSerializer>();
212+
services.AddTransient<IBrokeredMessageSerializer<ScanAndSignMessage>, ScanAndSignMessageSerializer>();
207213
services.AddTransient<IValidatorStateService, ValidatorStateService>();
208214
services.AddTransient<ISimpleCloudBlobProvider, SimpleCloudBlobProvider>();
209215
services.AddTransient<PackageSignatureProcessor>();
@@ -329,6 +335,7 @@ private static IServiceProvider CreateProvider(IServiceCollection services)
329335

330336
ConfigurePackageSigningValidators(containerBuilder);
331337
ConfigurePackageCertificatesValidator(containerBuilder);
338+
ConfigureScanAndSignProcessor(containerBuilder);
332339

333340
return new AutofacServiceProvider(containerBuilder.Build());
334341
}
@@ -407,6 +414,34 @@ private static void ConfigurePackageCertificatesValidator(ContainerBuilder build
407414
.As<PackageCertificatesValidator>();
408415
}
409416

417+
private static void ConfigureScanAndSignProcessor(ContainerBuilder builder)
418+
{
419+
builder
420+
.Register(c =>
421+
{
422+
var configuration = c.Resolve<IOptionsSnapshot<ScanAndSignConfiguration>>().Value.ServiceBus;
423+
return new TopicClientWrapper(configuration.ConnectionString, configuration.TopicPath);
424+
})
425+
.Keyed<ITopicClient>(ScanAndSignBindingKey);
426+
427+
builder
428+
.RegisterType<ValidatorStateService>()
429+
.WithParameter(
430+
(pi, ctx) => pi.ParameterType == typeof(string),
431+
(pi, ctx) => ValidatorName.ScanAndSign)
432+
.Keyed<IValidatorStateService>(ScanAndSignBindingKey);
433+
434+
builder
435+
.RegisterType<ScanAndSignEnqueuer>()
436+
.WithKeyedParameter(typeof(ITopicClient), ScanAndSignBindingKey)
437+
.As<IScanAndSignEnqueuer>();
438+
439+
builder
440+
.RegisterType<ScanAndSignProcessor>()
441+
.WithKeyedParameter(typeof(IValidatorStateService), ScanAndSignBindingKey)
442+
.AsSelf();
443+
}
444+
410445
private T GetRequiredService<T>()
411446
{
412447
return _serviceProvider.GetRequiredService<T>();

src/NuGet.Services.Validation.Orchestrator/NuGet.Services.Validation.Orchestrator.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@
6767
<Compile Include="PackageSigning\ProcessSignature\PackageSignatureProcessor.cs" />
6868
<Compile Include="PackageSigning\ProcessSignature\ProcessSignatureConfiguration.cs" />
6969
<Compile Include="PackageSigning\ProcessSignature\ProcessSignatureEnqueuer.cs" />
70+
<Compile Include="PackageSigning\ScanAndSign\IScanAndSignEnqueuer.cs" />
71+
<Compile Include="PackageSigning\ScanAndSign\ScanAndSignConfiguration.cs" />
72+
<Compile Include="PackageSigning\ScanAndSign\ScanAndSignEnqueuer.cs" />
73+
<Compile Include="PackageSigning\ScanAndSign\ScanAndSignProcessor.cs" />
7074
<Compile Include="PackageSigning\ValidateCertificate\IValidateCertificateEnqueuer.cs" />
7175
<Compile Include="PackageSigning\ValidateCertificate\PackageCertificatesValidator.cs" />
7276
<Compile Include="PackageSigning\ValidateCertificate\ValidateCertificateConfiguration.cs" />
@@ -129,7 +133,12 @@
129133
<Project>{91C060DA-736F-4DA9-A57F-CB3AC0E6CB10}</Project>
130134
<Name>Validation.PackageSigning.Core</Name>
131135
</ProjectReference>
136+
<ProjectReference Include="..\Validation.ScanAndSign.Core\Validation.ScanAndSign.Core.csproj">
137+
<Project>{dfac2769-4b67-4fbc-ad60-d93a39dd45ae}</Project>
138+
<Name>Validation.ScanAndSign.Core</Name>
139+
</ProjectReference>
132140
</ItemGroup>
141+
<ItemGroup />
133142
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
134143
<PropertyGroup>
135144
<SignPath>..\..\build</SignPath>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Threading.Tasks;
5+
using NuGet.Jobs.Validation.ScanAndSign;
6+
7+
namespace NuGet.Services.Validation.Orchestrator.PackageSigning.ScanAndSign
8+
{
9+
public interface IScanAndSignEnqueuer
10+
{
11+
/// <summary>
12+
/// Enqueues Scan operation.
13+
/// </summary>
14+
/// <param name="request">Request data</param>
15+
Task EnqueueScanAsync(IValidationRequest request);
16+
}
17+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using NuGet.Jobs.Configuration;
6+
7+
namespace NuGet.Services.Validation.Orchestrator.PackageSigning.ScanAndSign
8+
{
9+
public class ScanAndSignConfiguration
10+
{
11+
/// <summary>
12+
/// The Service Bus configuration used to enqueue package signing validations.
13+
/// </summary>
14+
public ServiceBusConfiguration ServiceBus { get; set; }
15+
16+
/// <summary>
17+
/// The visibility delay to apply to Service Bus messages requesting a new validation.
18+
/// </summary>
19+
public TimeSpan? MessageDelay { get; set; }
20+
}
21+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using Microsoft.Extensions.Options;
7+
using NuGet.Jobs.Validation.ScanAndSign;
8+
using NuGet.Services.ServiceBus;
9+
10+
namespace NuGet.Services.Validation.Orchestrator.PackageSigning.ScanAndSign
11+
{
12+
public class ScanAndSignEnqueuer : IScanAndSignEnqueuer
13+
{
14+
private readonly ITopicClient _topicClient;
15+
private readonly IBrokeredMessageSerializer<ScanAndSignMessage> _serializer;
16+
private readonly ScanAndSignConfiguration _configuration;
17+
18+
public ScanAndSignEnqueuer(
19+
ITopicClient topicClient,
20+
IBrokeredMessageSerializer<ScanAndSignMessage> serializer,
21+
IOptionsSnapshot<ScanAndSignConfiguration> configurationAccessor)
22+
{
23+
_topicClient = topicClient ?? throw new ArgumentNullException(nameof(topicClient));
24+
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
25+
if (configurationAccessor == null)
26+
{
27+
throw new ArgumentNullException(nameof(configurationAccessor));
28+
}
29+
if (configurationAccessor.Value == null)
30+
{
31+
throw new ArgumentException($"{nameof(configurationAccessor.Value)} property is null", nameof(configurationAccessor));
32+
}
33+
_configuration = configurationAccessor.Value;
34+
}
35+
36+
public Task EnqueueScanAsync(IValidationRequest request)
37+
{
38+
if (request == null)
39+
{
40+
throw new ArgumentNullException(nameof(request));
41+
}
42+
43+
var message = new ScanAndSignMessage(
44+
OperationRequestType.Scan,
45+
request.ValidationId,
46+
new Uri(request.NupkgUrl));
47+
var brokeredMessage = _serializer.Serialize(message);
48+
49+
var visibleAt = DateTimeOffset.UtcNow + (_configuration.MessageDelay ?? TimeSpan.Zero);
50+
brokeredMessage.ScheduledEnqueueTimeUtc = visibleAt;
51+
52+
return _topicClient.SendAsync(brokeredMessage);
53+
}
54+
}
55+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using Microsoft.Extensions.Logging;
7+
using NuGet.Jobs.Validation;
8+
using NuGet.Jobs.Validation.PackageSigning.Storage;
9+
10+
namespace NuGet.Services.Validation.Orchestrator.PackageSigning.ScanAndSign
11+
{
12+
[ValidatorName(ValidatorName.ScanAndSign)]
13+
public class ScanAndSignProcessor : IProcessor
14+
{
15+
private readonly IValidatorStateService _validatorStateService;
16+
private readonly IScanAndSignEnqueuer _scanAndSignEnqueuer;
17+
private readonly ILogger<ScanAndSignProcessor> _logger;
18+
19+
public ScanAndSignProcessor(
20+
IValidatorStateService validatorStateService,
21+
IScanAndSignEnqueuer scanAndSignEnqueuer,
22+
ILogger<ScanAndSignProcessor> logger)
23+
{
24+
_validatorStateService = validatorStateService ?? throw new ArgumentNullException(nameof(validatorStateService));
25+
_scanAndSignEnqueuer = scanAndSignEnqueuer ?? throw new ArgumentNullException(nameof(scanAndSignEnqueuer));
26+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
27+
}
28+
29+
public Task CleanUpAsync(IValidationRequest request)
30+
{
31+
if (request == null)
32+
{
33+
throw new ArgumentNullException(nameof(request));
34+
}
35+
36+
// scan only for now does not require cleanup
37+
return Task.CompletedTask;
38+
}
39+
40+
public async Task<IValidationResult> GetResultAsync(IValidationRequest request)
41+
{
42+
if (request == null)
43+
{
44+
throw new ArgumentNullException(nameof(request));
45+
}
46+
47+
var validatorStatus = await _validatorStateService.GetStatusAsync(request);
48+
49+
return validatorStatus.ToValidationResult();
50+
}
51+
52+
public async Task<IValidationResult> StartAsync(IValidationRequest request)
53+
{
54+
if (request == null)
55+
{
56+
throw new ArgumentNullException(nameof(request));
57+
}
58+
59+
var validatorStatus = await _validatorStateService.GetStatusAsync(request);
60+
61+
if (validatorStatus.State != ValidationStatus.NotStarted)
62+
{
63+
_logger.LogWarning(
64+
"Scan and Sign validation with validation Id {ValidationId} ({PackageId} {PackageVersion}) has already started.",
65+
request.ValidationId,
66+
request.PackageId,
67+
request.PackageVersion);
68+
69+
return validatorStatus.ToValidationResult();
70+
}
71+
72+
// here we need to determine whether we do scan only or scan and repo sign.
73+
// Right now we only support scan only
74+
75+
await _scanAndSignEnqueuer.EnqueueScanAsync(request);
76+
var result = await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete);
77+
78+
return result.ToValidationResult();
79+
}
80+
}
81+
}

src/NuGet.Services.Validation.Orchestrator/settings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@
6666
},
6767
"MessageDelay": "00:00:05"
6868
},
69+
"ScanAndSign": {
70+
"ServiceBus": {
71+
"ConnectionString": "",
72+
"TopicPath": "",
73+
"SubscriptionName": ""
74+
},
75+
"MessageDelay": "00:00:05"
76+
},
6977
"RunnerConfiguration": {
7078
"ProcessRecycleInterval": "1:00:00:00",
7179
"ShutdownWaitInterval": "00:01:00"

src/Validation.Common.Job/Validation.Common.Job.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
<Version>2.23.0</Version>
101101
</PackageReference>
102102
<PackageReference Include="NuGet.Services.Validation">
103-
<Version>2.25.0-master-29664</Version>
103+
<Version>2.25.0-master-30453</Version>
104104
</PackageReference>
105105
<PackageReference Include="NuGetGallery.Core">
106106
<Version>4.4.4-dev-30533</Version>
@@ -118,6 +118,9 @@
118118
<Name>NuGet.Jobs.Common</Name>
119119
</ProjectReference>
120120
</ItemGroup>
121+
<ItemGroup>
122+
<None Include="Validation.Common.Job.nuspec" />
123+
</ItemGroup>
121124
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
122125
<PropertyGroup>
123126
<SignPath>..\..\build</SignPath>

0 commit comments

Comments
 (0)