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

Commit a843ac6

Browse files
authored
[Repository Signing] Add option to suppress repository signature extraction (#495)
1 parent f72ea77 commit a843ac6

7 files changed

Lines changed: 93 additions & 14 deletions

File tree

src/Validation.PackageSigning.ProcessSignature/ProcessSignatureConfiguration.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,11 @@ public class ProcessSignatureConfiguration
2020
/// repository signature is removed.
2121
/// </summary>
2222
public string V3ServiceIndexUrl { get; set; }
23+
24+
/// <summary>
25+
/// Whether repository signatures should be persisted to the database. Disable this if repository signing
26+
/// is in test mode and repository signed packages are not published.
27+
/// </summary>
28+
public bool CommitRepositorySignatures { get; set; }
2329
}
2430
}

src/Validation.PackageSigning.ProcessSignature/Settings/dev.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"AllowedRepositorySigningCertificates": [
2323
"cf6ce6768ef858a3a667be1af8aa524d386c7f59a34542713f5dfb0d79acf3dd"
2424
],
25-
"V3ServiceIndexUrl": "https://apidev.nugettest.org/v3/index.json"
25+
"V3ServiceIndexUrl": "https://apidev.nugettest.org/v3/index.json",
26+
"CommitRepositorySignatures": false
2627
},
2728

2829
"PackageDownloadTimeout": "00:10:00",

src/Validation.PackageSigning.ProcessSignature/Settings/int.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"AllowedRepositorySigningCertificates": [
2323
"cf6ce6768ef858a3a667be1af8aa524d386c7f59a34542713f5dfb0d79acf3dd"
2424
],
25-
"V3ServiceIndexUrl": "https://apiint.nugettest.org/v3/index.json"
25+
"V3ServiceIndexUrl": "https://apiint.nugettest.org/v3/index.json",
26+
"CommitRepositorySignatures": false
2627
},
2728

2829
"PackageDownloadTimeout": "00:10:00",

src/Validation.PackageSigning.ProcessSignature/Settings/prod.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"AllowedRepositorySigningCertificates": [
2323
"cf7ac17ad047ecd5fdc36822031b12d4ef078b6f2b4c5e6ba41f8ff2cf4bad67"
2424
],
25-
"V3ServiceIndexUrl": "https://api.nuget.org/v3/index.json"
25+
"V3ServiceIndexUrl": "https://api.nuget.org/v3/index.json",
26+
"CommitRepositorySignatures": false
2627
},
2728

2829
"PackageDownloadTimeout": "00:10:00",

src/Validation.PackageSigning.ProcessSignature/SignaturePartsExtractor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Threading;
99
using System.Threading.Tasks;
1010
using Microsoft.Extensions.Logging;
11+
using Microsoft.Extensions.Options;
1112
using NuGet.Jobs.Validation.PackageSigning.Storage;
1213
using NuGet.Packaging.Signing;
1314
using NuGet.Services.Validation;
@@ -18,15 +19,18 @@ public class SignaturePartsExtractor : ISignaturePartsExtractor
1819
{
1920
private readonly ICertificateStore _certificateStore;
2021
private readonly IValidationEntitiesContext _entitiesContext;
22+
private readonly IOptionsSnapshot<ProcessSignatureConfiguration> _configuration;
2123
private readonly ILogger<SignaturePartsExtractor> _logger;
2224

2325
public SignaturePartsExtractor(
2426
ICertificateStore certificateStore,
2527
IValidationEntitiesContext entitiesContext,
28+
IOptionsSnapshot<ProcessSignatureConfiguration> configuration,
2629
ILogger<SignaturePartsExtractor> logger)
2730
{
2831
_certificateStore = certificateStore ?? throw new ArgumentNullException(nameof(certificateStore));
2932
_entitiesContext = entitiesContext ?? throw new ArgumentNullException(nameof(entitiesContext));
33+
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
3034
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
3135
}
3236

@@ -227,6 +231,12 @@ private async Task InitializePackageSignatureAndTrustedTimestampAsync(
227231
return;
228232
}
229233

234+
if (type == PackageSignatureType.Repository && !_configuration.Value.CommitRepositorySignatures)
235+
{
236+
_logger.LogInformation("Skipping initialization of repository signature due to configuration!");
237+
return;
238+
}
239+
230240
// Initialize the package signature record.
231241
var packageSignature = await InitializePackageSignatureAsync(
232242
packageKey,

tests/Validation.PackageSigning.ProcessSignature.Tests/SignaturePartsExtractorFacts.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
using System.Threading;
1111
using System.Threading.Tasks;
1212
using Microsoft.Extensions.Logging;
13+
using Microsoft.Extensions.Options;
1314
using Moq;
15+
using NuGet.Jobs.Validation.PackageSigning;
1416
using NuGet.Jobs.Validation.PackageSigning.ProcessSignature;
1517
using NuGet.Jobs.Validation.PackageSigning.Storage;
1618
using NuGet.Packaging.Signing;
@@ -62,7 +64,7 @@ public class SignaturePartsExtractorFacts
6264
"CN=NUGET_DO_NOT_TRUST.root.test.test, OU=Test Organizational Unit Name, O=Test Organization Name, L=Redmond, S=WA, C=US",
6365
TestResources.RootThumbprint),
6466
},
65-
TimestampEndCertificate = new SubjectAndThumbprint(
67+
TimestampEndCertificate = new SubjectAndThumbprint(
6668
"CN=Symantec SHA256 TimeStamping Signer - G2, OU=Symantec Trust Network, O=Symantec Corporation, C=US",
6769
TestResources.Leaf1TimestampThumbprint),
6870
TimestampParentCertificates = new[]
@@ -116,6 +118,8 @@ public class ExtractAsync
116118
private readonly Mock<ICertificateStore> _certificateStore;
117119
private readonly List<X509Certificate2> _savedCertificates;
118120
private readonly Mock<IValidationEntitiesContext> _entitiesContext;
121+
private readonly Mock<IOptionsSnapshot<ProcessSignatureConfiguration>> _configAccessor;
122+
private readonly ProcessSignatureConfiguration _config;
119123
private readonly Mock<ILogger<SignaturePartsExtractor>> _logger;
120124
private readonly SignaturePartsExtractor _target;
121125

@@ -152,11 +156,20 @@ public ExtractAsync()
152156
.Setup(x => x.TrustedTimestamps)
153157
.Returns(DbSetMockFactory.Create<TrustedTimestamp>());
154158

159+
_configAccessor = new Mock<IOptionsSnapshot<ProcessSignatureConfiguration>>();
160+
_config = new ProcessSignatureConfiguration
161+
{
162+
CommitRepositorySignatures = true
163+
};
164+
165+
_configAccessor.Setup(a => a.Value).Returns(_config);
166+
155167
_logger = new Mock<ILogger<SignaturePartsExtractor>>();
156168

157169
_target = new SignaturePartsExtractor(
158170
_certificateStore.Object,
159171
_entitiesContext.Object,
172+
_configAccessor.Object,
160173
_logger.Object);
161174
}
162175

@@ -616,6 +629,51 @@ public async Task IgnoreExtraCertificates()
616629
signature.SignedCms.Certificates.Count + signature.Timestamps.Sum(x => x.SignedCms.Certificates.Count));
617630
}
618631

632+
[Fact]
633+
public async Task IfRepositorySignatureExtractionIsDisabled_IgnoresRepositorySignatureOnRepositorySignedPackage()
634+
{
635+
// Arrange
636+
var signature = await TestResources.LoadPrimarySignatureAsync(TestResources.RepoSignedPackageLeaf1);
637+
638+
_entitiesContext
639+
.Setup(x => x.PackageSignatures)
640+
.Returns(DbSetMockFactory.Create<PackageSignature>());
641+
642+
_config.CommitRepositorySignatures = false;
643+
644+
// Act
645+
await _target.ExtractAsync(_packageKey, signature, _token);
646+
647+
// Assert
648+
Assert.Equal(0, _entitiesContext.Object.PackageSignatures.Count());
649+
650+
// The repository signature's certificate is still stored on blob storage.
651+
VerifyStoredCertificates(Leaf1Certificates);
652+
}
653+
654+
[Fact]
655+
public async Task IfRepositorySignatureExtractionIsDisabled_IgnoresRepositorySignatureOnRepositoryCounterSignedPackage()
656+
{
657+
// Arrange
658+
var signature = await TestResources.LoadPrimarySignatureAsync(TestResources.AuthorAndRepoSignedPackageLeaf1);
659+
660+
_entitiesContext
661+
.Setup(x => x.PackageSignatures)
662+
.Returns(DbSetMockFactory.Create<PackageSignature>());
663+
664+
_config.CommitRepositorySignatures = false;
665+
666+
// Act
667+
await _target.ExtractAsync(_packageKey, signature, _token);
668+
669+
// Assert
670+
Assert.Equal(1, _entitiesContext.Object.PackageSignatures.Count());
671+
Assert.Equal(PackageSignatureType.Author, _entitiesContext.Object.PackageSignatures.First().Type);
672+
673+
// The repository signature's certificate is still stored on blob storage.
674+
VerifyStoredCertificates(AuthorAndRepoSignedCertificates);
675+
}
676+
619677
private void AssignIds()
620678
{
621679
var endCertificates = _entitiesContext.Object.EndCertificates.AsQueryable().ToList();

tests/Validation.PackageSigning.ProcessSignature.Tests/SignatureValidatorIntegrationTests.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,21 @@ public SignatureValidatorIntegrationTests(CertificateIntegrationTestFixture fixt
119119

120120
_certificateStore = new Mock<ICertificateStore>();
121121

122+
// These dependencies are concrete.
123+
_configuration = new ProcessSignatureConfiguration
124+
{
125+
AllowedRepositorySigningCertificates = new List<string> { "fake-thumbprint" },
126+
V3ServiceIndexUrl = TestResources.V3ServiceIndexUrl,
127+
CommitRepositorySignatures = true,
128+
};
129+
_optionsSnapshot = new Mock<IOptionsSnapshot<ProcessSignatureConfiguration>>();
130+
_optionsSnapshot.Setup(x => x.Value).Returns(() => _configuration);
131+
_formatValidator = new SignatureFormatValidator(_optionsSnapshot.Object);
132+
122133
_signaturePartsExtractor = new SignaturePartsExtractor(
123134
_certificateStore.Object,
124135
_validationEntitiesContext.Object,
136+
_optionsSnapshot.Object,
125137
loggerFactory.CreateLogger<SignaturePartsExtractor>());
126138

127139
_packageFileService = new Mock<IProcessorPackageFileService>();
@@ -144,16 +156,6 @@ public SignatureValidatorIntegrationTests(CertificateIntegrationTestFixture fixt
144156

145157
_corePackageService = new Mock<ICorePackageService>();
146158

147-
// These dependencies are concrete.
148-
_configuration = new ProcessSignatureConfiguration
149-
{
150-
AllowedRepositorySigningCertificates = new List<string> { "fake-thumbprint" },
151-
V3ServiceIndexUrl = TestResources.V3ServiceIndexUrl,
152-
};
153-
_optionsSnapshot = new Mock<IOptionsSnapshot<ProcessSignatureConfiguration>>();
154-
_optionsSnapshot.Setup(x => x.Value).Returns(() => _configuration);
155-
_formatValidator = new SignatureFormatValidator(_optionsSnapshot.Object);
156-
157159
_telemetryClient = new Mock<ITelemetryClient>();
158160
_telemetryService = new TelemetryService(_telemetryClient.Object);
159161

0 commit comments

Comments
 (0)