Merge branch 'main' of https://git.stella-ops.org/stella-ops.org/git.stella-ops.org
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// FixIndexBuilderIntegrationTests.cs
|
||||
// Sprint: SPRINT_20251226_012_BINIDX_backport_handling
|
||||
// Task: BACKPORT-20 — Integration tests for fix index building
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.BinaryIndex.FixIndex.Models;
|
||||
using StellaOps.BinaryIndex.FixIndex.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Core.Tests.FixIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for the FixIndexBuilder covering end-to-end scenarios.
|
||||
/// </summary>
|
||||
public class FixIndexBuilderIntegrationTests
|
||||
{
|
||||
private readonly FixIndexBuilder _sut;
|
||||
private readonly Guid _testSnapshotId = Guid.NewGuid();
|
||||
|
||||
public FixIndexBuilderIntegrationTests()
|
||||
{
|
||||
_sut = new FixIndexBuilder(NullLogger<FixIndexBuilder>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDebianIndexAsync_WithChangelogAndPatches_CombinesEvidence()
|
||||
{
|
||||
// Arrange
|
||||
var changelog = """
|
||||
openssl (3.0.11-1~deb12u2) bookworm-security; urgency=high
|
||||
|
||||
* Fix CVE-2024-0727: PKCS12 decoding crash
|
||||
* Fix CVE-2024-2511: memory leak in TLSv1.3
|
||||
|
||||
-- Debian Security Team <security@debian.org> Mon, 15 Jan 2024 10:00:00 +0000
|
||||
""";
|
||||
|
||||
var patches = new List<PatchFile>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Path = "debian/patches/CVE-2024-3333.patch",
|
||||
Content = """
|
||||
Description: Fix integer overflow
|
||||
CVE: CVE-2024-3333
|
||||
Origin: upstream, https://github.com/openssl/commit/abc123
|
||||
|
||||
--- a/src/parser.c
|
||||
+++ b/src/parser.c
|
||||
""",
|
||||
Sha256 = "abcd1234"
|
||||
}
|
||||
};
|
||||
|
||||
var request = new DebianFixIndexRequest
|
||||
{
|
||||
Distro = "debian",
|
||||
Release = "bookworm",
|
||||
SourcePkg = "openssl",
|
||||
Changelog = changelog,
|
||||
Patches = patches,
|
||||
Version = "3.0.11-1~deb12u2",
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildDebianIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().HaveCount(3);
|
||||
results.Should().Contain(e => e.CveId == "CVE-2024-0727");
|
||||
results.Should().Contain(e => e.CveId == "CVE-2024-2511");
|
||||
results.Should().Contain(e => e.CveId == "CVE-2024-3333");
|
||||
|
||||
// Patch evidence should have higher confidence
|
||||
var patchEvidence = results.First(e => e.CveId == "CVE-2024-3333");
|
||||
patchEvidence.Method.Should().Be(FixMethod.PatchHeader);
|
||||
patchEvidence.Confidence.Should().BeGreaterThan(0.85m);
|
||||
|
||||
// All should reference the snapshot
|
||||
results.Should().AllSatisfy(e => e.SnapshotId.Should().Be(_testSnapshotId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildAlpineIndexAsync_WithSecfixes_ExtractsAllCves()
|
||||
{
|
||||
// Arrange
|
||||
var apkbuild = """
|
||||
pkgname=curl
|
||||
pkgver=8.5.0
|
||||
pkgrel=1
|
||||
|
||||
# secfixes:
|
||||
# 8.5.0-r0:
|
||||
# - CVE-2023-46218
|
||||
# - CVE-2023-46219
|
||||
# 8.4.0-r0:
|
||||
# - CVE-2023-38545
|
||||
# - CVE-2023-38546
|
||||
|
||||
build() {
|
||||
./configure
|
||||
}
|
||||
""";
|
||||
|
||||
var request = new AlpineFixIndexRequest
|
||||
{
|
||||
Release = "v3.19",
|
||||
SourcePkg = "curl",
|
||||
ApkBuild = apkbuild,
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildAlpineIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().HaveCount(4);
|
||||
results.Should().Contain(e => e.CveId == "CVE-2023-46218" && e.FixedVersion == "8.5.0-r0");
|
||||
results.Should().Contain(e => e.CveId == "CVE-2023-46219" && e.FixedVersion == "8.5.0-r0");
|
||||
results.Should().Contain(e => e.CveId == "CVE-2023-38545" && e.FixedVersion == "8.4.0-r0");
|
||||
results.Should().Contain(e => e.CveId == "CVE-2023-38546" && e.FixedVersion == "8.4.0-r0");
|
||||
|
||||
results.Should().AllSatisfy(e =>
|
||||
{
|
||||
e.Distro.Should().Be("alpine");
|
||||
e.Release.Should().Be("v3.19");
|
||||
e.Method.Should().Be(FixMethod.SecurityFeed);
|
||||
e.Confidence.Should().Be(0.95m);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildRpmIndexAsync_WithMultipleChangelogEntries_ExtractsAllCves()
|
||||
{
|
||||
// Arrange
|
||||
var specContent = """
|
||||
Name: kernel
|
||||
Version: 6.6.0
|
||||
Release: 100.el9
|
||||
|
||||
%description
|
||||
The Linux Kernel
|
||||
|
||||
%changelog
|
||||
* Mon Dec 15 2024 Security <security@redhat.com> - 6.6.0-100
|
||||
- Fix CVE-2024-1111: stack buffer overflow
|
||||
- Fix CVE-2024-2222: use-after-free in netfilter
|
||||
|
||||
* Mon Nov 01 2024 Security <security@redhat.com> - 6.5.0-50
|
||||
- Fix CVE-2024-3333: information disclosure
|
||||
""";
|
||||
|
||||
var request = new RpmFixIndexRequest
|
||||
{
|
||||
Distro = "rhel",
|
||||
Release = "9",
|
||||
SourcePkg = "kernel",
|
||||
SpecContent = specContent,
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildRpmIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().HaveCount(3);
|
||||
|
||||
var v100Fixes = results.Where(e => e.FixedVersion == "6.6.0-100").ToList();
|
||||
v100Fixes.Should().HaveCount(2);
|
||||
v100Fixes.Should().Contain(e => e.CveId == "CVE-2024-1111");
|
||||
v100Fixes.Should().Contain(e => e.CveId == "CVE-2024-2222");
|
||||
|
||||
var v50Fixes = results.Where(e => e.FixedVersion == "6.5.0-50").ToList();
|
||||
v50Fixes.Should().HaveCount(1);
|
||||
v50Fixes[0].CveId.Should().Be("CVE-2024-3333");
|
||||
|
||||
results.Should().AllSatisfy(e =>
|
||||
{
|
||||
e.Distro.Should().Be("rhel");
|
||||
e.Release.Should().Be("9");
|
||||
e.Method.Should().Be(FixMethod.Changelog);
|
||||
e.Confidence.Should().Be(0.75m);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDebianIndexAsync_WithEmptyInputs_ReturnsEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var request = new DebianFixIndexRequest
|
||||
{
|
||||
Distro = "debian",
|
||||
Release = "bookworm",
|
||||
SourcePkg = "empty-pkg",
|
||||
Changelog = "",
|
||||
Patches = [],
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildDebianIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildAlpineIndexAsync_WithNoSecfixes_ReturnsEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var apkbuild = """
|
||||
pkgname=simple
|
||||
pkgver=1.0
|
||||
pkgrel=0
|
||||
|
||||
build() {
|
||||
make
|
||||
}
|
||||
""";
|
||||
|
||||
var request = new AlpineFixIndexRequest
|
||||
{
|
||||
Release = "v3.19",
|
||||
SourcePkg = "simple",
|
||||
ApkBuild = apkbuild,
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildAlpineIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildRpmIndexAsync_WithNoChangelog_ReturnsEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var specContent = """
|
||||
Name: simple
|
||||
Version: 1.0
|
||||
Release: 1
|
||||
|
||||
%description
|
||||
A simple package
|
||||
""";
|
||||
|
||||
var request = new RpmFixIndexRequest
|
||||
{
|
||||
Distro = "fedora",
|
||||
Release = "39",
|
||||
SourcePkg = "simple",
|
||||
SpecContent = specContent,
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildRpmIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert
|
||||
results.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDebianIndexAsync_DeduplicatesCvesFromChangelogAndPatches()
|
||||
{
|
||||
// Arrange - Same CVE mentioned in both changelog and patch
|
||||
var changelog = """
|
||||
pkg (1.0-1) stable; urgency=high
|
||||
|
||||
* Fix CVE-2024-5555
|
||||
|
||||
-- Maintainer <m@x.com> Mon, 01 Jan 2024 12:00:00 +0000
|
||||
""";
|
||||
|
||||
var patches = new List<PatchFile>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Path = "debian/patches/CVE-2024-5555.patch",
|
||||
Content = """
|
||||
CVE: CVE-2024-5555
|
||||
|
||||
--- a/foo.c
|
||||
+++ b/foo.c
|
||||
""",
|
||||
Sha256 = "hash123"
|
||||
}
|
||||
};
|
||||
|
||||
var request = new DebianFixIndexRequest
|
||||
{
|
||||
Distro = "debian",
|
||||
Release = "stable",
|
||||
SourcePkg = "pkg",
|
||||
Changelog = changelog,
|
||||
Patches = patches,
|
||||
Version = "1.0-1",
|
||||
SnapshotId = _testSnapshotId
|
||||
};
|
||||
|
||||
// Act
|
||||
var results = new List<FixEvidence>();
|
||||
await foreach (var evidence in _sut.BuildDebianIndexAsync(request))
|
||||
{
|
||||
results.Add(evidence);
|
||||
}
|
||||
|
||||
// Assert - Both are returned (patch with higher confidence overrides)
|
||||
// The implementation allows both but prefers patch evidence
|
||||
var cve5555 = results.Where(e => e.CveId == "CVE-2024-5555").ToList();
|
||||
cve5555.Should().HaveCountGreaterOrEqualTo(1);
|
||||
cve5555.Should().Contain(e => e.Method == FixMethod.PatchHeader);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.BinaryIndex.Core\StellaOps.BinaryIndex.Core.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.BinaryIndex.FixIndex\StellaOps.BinaryIndex.FixIndex.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user