feat: Implement BerkeleyDB reader for RPM databases
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
console-runner-image / build-runner-image (push) Has been cancelled
wine-csp-build / Build Wine CSP Image (push) Has been cancelled
wine-csp-build / Integration Tests (push) Has been cancelled
wine-csp-build / Security Scan (push) Has been cancelled
wine-csp-build / Generate SBOM (push) Has been cancelled
wine-csp-build / Publish Image (push) Has been cancelled
wine-csp-build / Air-Gap Bundle (push) Has been cancelled
wine-csp-build / Test Summary (push) Has been cancelled

- Added BerkeleyDbReader class to read and extract RPM header blobs from BerkeleyDB hash databases.
- Implemented methods to detect BerkeleyDB format and extract values, including handling of page sizes and magic numbers.
- Added tests for BerkeleyDbReader to ensure correct functionality and header extraction.

feat: Add Yarn PnP data tests

- Created YarnPnpDataTests to validate package resolution and data loading from Yarn PnP cache.
- Implemented tests for resolved keys, package presence, and loading from cache structure.

test: Add egg-info package fixtures for Python tests

- Created egg-info package fixtures for testing Python analyzers.
- Included PKG-INFO, entry_points.txt, and installed-files.txt for comprehensive coverage.

test: Enhance RPM database reader tests

- Added tests for RpmDatabaseReader to validate fallback to legacy packages when SQLite is missing.
- Implemented helper methods to create legacy package files and RPM headers for testing.

test: Implement dual signing tests

- Added DualSignTests to validate secondary signature addition when configured.
- Created stub implementations for crypto providers and key resolvers to facilitate testing.

chore: Update CI script for Playwright Chromium installation

- Modified ci-console-exports.sh to ensure deterministic Chromium binary installation for console exports tests.
- Added checks for Windows compatibility and environment variable setups for Playwright browsers.
This commit is contained in:
StellaOps Bot
2025-12-07 16:24:45 +02:00
parent e3f28a21ab
commit 11597679ed
199 changed files with 9809 additions and 4404 deletions

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using StellaOps.Cryptography;
using StellaOps.Signer.Core;
using StellaOps.Signer.Infrastructure.Signing;
using Xunit;
namespace StellaOps.Signer.Tests.Signing;
public class DualSignTests
{
[Fact]
public async Task AddsSecondarySignature_WhenConfigured()
{
Environment.SetEnvironmentVariable("PQ_SOFT_ALLOWED", "1");
var registry = new CryptoProviderRegistry(new ICryptoProvider[] { new StubProvider() });
var resolver = new StubKeyResolver("primary-key", "stub");
var options = Options.Create(new DsseSignerOptions
{
KeylessAlgorithm = SignatureAlgorithms.Es256,
SecondaryAlgorithm = SignatureAlgorithms.Falcon512,
SecondaryProvider = "stub",
SecondaryKeyId = "secondary-key"
});
var signer = new CryptoDsseSigner(registry, resolver, options, NullLogger<CryptoDsseSigner>.Instance);
var request = new SigningRequest(
Options: new SigningOptions(SigningMode.Keyless),
Payload: Array.Empty<byte>(),
Subjects: Array.Empty<SigningSubject>(),
PredicateType: "demo");
var entitlement = new ProofOfEntitlementResult(true, "entitled", Array.Empty<string>());
var caller = new CallerContext("tenant", "subject", "plan", "scanner-digest");
var bundle = await signer.SignAsync(request, entitlement, caller, CancellationToken.None);
bundle.Envelope.Signatures.Should().HaveCount(2);
bundle.Envelope.Signatures[0].KeyId.Should().Be("primary-key");
bundle.Envelope.Signatures[1].KeyId.Should().Be("secondary-key");
}
private sealed class StubProvider : ICryptoProvider
{
public string Name => "stub";
public bool Supports(CryptoCapability capability, string algorithmId) =>
capability == CryptoCapability.Signing;
public IPasswordHasher GetPasswordHasher(string algorithmId) => throw new NotSupportedException();
public ICryptoHasher GetHasher(string algorithmId) => throw new NotSupportedException();
public ICryptoSigner GetSigner(string algorithmId, CryptoKeyReference keyReference) =>
new StubSigner(keyReference.KeyId, algorithmId);
public void UpsertSigningKey(CryptoSigningKey signingKey) { }
public bool RemoveSigningKey(string keyId) => true;
public IReadOnlyCollection<CryptoSigningKey> GetSigningKeys() => Array.Empty<CryptoSigningKey>();
}
private sealed class StubSigner : ICryptoSigner
{
public StubSigner(string keyId, string algorithmId)
{
KeyId = keyId;
AlgorithmId = algorithmId;
}
public string KeyId { get; }
public string AlgorithmId { get; }
public ValueTask<byte[]> SignAsync(ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default)
{
var payload = System.Text.Encoding.UTF8.GetBytes($"{AlgorithmId}:{KeyId}");
return ValueTask.FromResult(payload);
}
public ValueTask<bool> VerifyAsync(ReadOnlyMemory<byte> data, ReadOnlyMemory<byte> signature, CancellationToken cancellationToken = default)
=> ValueTask.FromResult(true);
public Microsoft.IdentityModel.Tokens.JsonWebKey ExportPublicJsonWebKey()
=> new() { Kid = KeyId, Alg = AlgorithmId, Kty = "oct" };
}
private sealed class StubKeyResolver : ISigningKeyResolver
{
private readonly string keyId;
private readonly string provider;
public StubKeyResolver(string keyId, string provider)
{
this.keyId = keyId;
this.provider = provider;
}
public Task<SigningKeyResolution> ResolveKeyAsync(SigningMode mode, string tenant, CancellationToken cancellationToken)
{
return Task.FromResult(new SigningKeyResolution(
keyId,
provider,
issuer: null,
subject: null,
expiresAtUtc: null,
certificateChain: Array.Empty<string>()));
}
}
}