audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit.v3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -311,7 +312,7 @@ public sealed class CombinedRuntimeAdapter : IExportAdapter
|
||||
writer.WriteString("type", "combined.header");
|
||||
writer.WriteString("version", "1.0.0");
|
||||
writer.WriteString("schema", "stellaops.combined.runtime@v1");
|
||||
writer.WriteString("generated_at", timestamp.UtcDateTime.ToString("O"));
|
||||
writer.WriteString("generated_at", timestamp.UtcDateTime.ToString("O", CultureInfo.InvariantCulture));
|
||||
writer.WriteString("tenant_id", context.TenantId.ToString("D"));
|
||||
if (!string.IsNullOrEmpty(context.CorrelationId))
|
||||
{
|
||||
@@ -342,7 +343,7 @@ public sealed class CombinedRuntimeAdapter : IExportAdapter
|
||||
writer.WriteNumber("runtime_events", runtimeEventCount);
|
||||
writer.WriteNumber("total", entryTraceCount + runtimeEventCount);
|
||||
writer.WriteEndObject();
|
||||
writer.WriteString("completed_at", timestamp.UtcDateTime.ToString("O"));
|
||||
writer.WriteString("completed_at", timestamp.UtcDateTime.ToString("O", CultureInfo.InvariantCulture));
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Formats.Tar;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -217,7 +218,7 @@ public sealed class DevPortalOfflineBundleBuilder
|
||||
builder.AppendLine("DevPortal Offline Bundle");
|
||||
builder.AppendLine("========================");
|
||||
builder.Append("Bundle ID: ").AppendLine(manifest.BundleId.ToString("D"));
|
||||
builder.Append("Generated At: ").AppendLine(manifest.GeneratedAt.ToString("O"));
|
||||
builder.Append("Generated At: ").AppendLine(manifest.GeneratedAt.ToString("O", CultureInfo.InvariantCulture));
|
||||
|
||||
if (manifest.Metadata.TryGetValue("releaseVersion", out var releaseVersion))
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Buffers.Binary;
|
||||
using System.Formats.Tar;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -431,8 +432,8 @@ public sealed class MirrorBundleBuilder
|
||||
if (manifest.Selectors.TimeWindow is not null)
|
||||
{
|
||||
builder.AppendLine(" timeWindow:");
|
||||
builder.Append(" from: ").AppendLine(manifest.Selectors.TimeWindow.From.ToString("O"));
|
||||
builder.Append(" to: ").AppendLine(manifest.Selectors.TimeWindow.To.ToString("O"));
|
||||
builder.Append(" from: ").AppendLine(manifest.Selectors.TimeWindow.From.ToString("O", CultureInfo.InvariantCulture));
|
||||
builder.Append(" to: ").AppendLine(manifest.Selectors.TimeWindow.To.ToString("O", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
builder.AppendLine("counts:");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Cryptography;
|
||||
@@ -47,7 +48,7 @@ public sealed class ExportWebhookClient : IExportWebhookClient
|
||||
|
||||
// Add standard headers
|
||||
request.Headers.Add(ExportNotificationHeaders.EventType, eventType);
|
||||
request.Headers.Add(ExportNotificationHeaders.SentAt, sentAt.ToString("O"));
|
||||
request.Headers.Add(ExportNotificationHeaders.SentAt, sentAt.ToString("O", CultureInfo.InvariantCulture));
|
||||
|
||||
// Add signature if signing key is configured
|
||||
if (!string.IsNullOrWhiteSpace(_options.SigningKey))
|
||||
@@ -118,7 +119,7 @@ public sealed class ExportWebhookClient : IExportWebhookClient
|
||||
public static string ComputeSignature(string payload, DateTimeOffset sentAt, string signingKey)
|
||||
{
|
||||
// PAE (Pre-Authentication Encoding) style: timestamp.payload
|
||||
var signatureInput = $"{sentAt:O}.{payload}";
|
||||
var signatureInput = $"{sentAt.ToString("O", CultureInfo.InvariantCulture)}.{payload}";
|
||||
var inputBytes = Encoding.UTF8.GetBytes(signatureInput);
|
||||
|
||||
byte[] keyBytes;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Formats.Tar;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
@@ -273,7 +274,7 @@ public sealed class OfflineBundlePackager : IOfflineBundlePackager
|
||||
alert_id = request.AlertId,
|
||||
tenant_id = request.TenantId,
|
||||
artifact_id = request.ArtifactId,
|
||||
created_at = now.ToString("O"),
|
||||
created_at = now.ToString("O", CultureInfo.InvariantCulture),
|
||||
created_by = request.ActorId
|
||||
};
|
||||
entries.Add(await WriteJsonEntryAsync(
|
||||
@@ -283,7 +284,7 @@ public sealed class OfflineBundlePackager : IOfflineBundlePackager
|
||||
var artifactMetadata = new
|
||||
{
|
||||
artifact_id = request.ArtifactId,
|
||||
captured_at = now.ToString("O")
|
||||
captured_at = now.ToString("O", CultureInfo.InvariantCulture)
|
||||
};
|
||||
entries.Add(await WriteJsonEntryAsync(
|
||||
tempDir, "metadata/artifact.json", BundleEntryTypes.Metadata, artifactMetadata, cancellationToken));
|
||||
@@ -291,8 +292,8 @@ public sealed class OfflineBundlePackager : IOfflineBundlePackager
|
||||
// Write timestamps
|
||||
var timestamps = new
|
||||
{
|
||||
bundle_created_at = now.ToString("O"),
|
||||
evidence_captured_at = now.ToString("O"),
|
||||
bundle_created_at = now.ToString("O", CultureInfo.InvariantCulture),
|
||||
evidence_captured_at = now.ToString("O", CultureInfo.InvariantCulture),
|
||||
baseline_scan_id = request.BaselineScanId
|
||||
};
|
||||
entries.Add(await WriteJsonEntryAsync(
|
||||
@@ -313,7 +314,7 @@ public sealed class OfflineBundlePackager : IOfflineBundlePackager
|
||||
{
|
||||
status = "pending",
|
||||
alert_id = request.AlertId,
|
||||
computed_at = _timeProvider.GetUtcNow().ToString("O")
|
||||
computed_at = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture)
|
||||
};
|
||||
entries.Add(await WriteJsonEntryAsync(
|
||||
tempDir, "evidence/reachability.json", BundleEntryTypes.Evidence, reachability, cancellationToken));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using System.Globalization;
|
||||
using StellaOps.Provcache;
|
||||
using StellaOps.Provcache.Oci;
|
||||
|
||||
@@ -129,7 +130,7 @@ public sealed class ProvcacheOciExporter : IProvcacheOciExporter
|
||||
{
|
||||
var annotations = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||
{
|
||||
["org.opencontainers.image.created"] = _timeProvider.GetUtcNow().ToString("O"),
|
||||
["org.opencontainers.image.created"] = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture),
|
||||
["org.opencontainers.image.title"] = "stellaops.provcache.decision",
|
||||
["org.opencontainers.image.description"] = "Provcache decision attestation",
|
||||
["stellaops.provcache.verikey"] = request.DecisionDigest.VeriKey,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -264,7 +265,7 @@ public sealed class EvidencePackSigningService : IEvidencePackSigningService
|
||||
MerkleRoot = pack.Manifest!.MerkleRoot,
|
||||
FileCount = pack.Manifest.FileCount,
|
||||
TotalSizeBytes = pack.Manifest.TotalSizeBytes,
|
||||
GeneratedAt = pack.GeneratedAt.ToString("O"),
|
||||
GeneratedAt = pack.GeneratedAt.ToString("O", CultureInfo.InvariantCulture),
|
||||
SbomFormats = pack.SbomDocuments.Select(s => $"{s.Format}@{s.FormatVersion}").ToList(),
|
||||
VexFormats = pack.VexDocuments.Select(v => $"{v.Format}@{v.FormatVersion}").ToList(),
|
||||
HasPolicyVerdict = pack.PolicyVerdict is not null,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -349,7 +350,7 @@ public sealed class LineageEvidencePackService : ILineageEvidencePackService
|
||||
bomFormat = "CycloneDX",
|
||||
specVersion = "1.6",
|
||||
version = 1,
|
||||
metadata = new { timestamp = _timeProvider.GetUtcNow().ToString("O") },
|
||||
metadata = new { timestamp = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture) },
|
||||
components = Array.Empty<object>()
|
||||
}, JsonOptions);
|
||||
|
||||
@@ -385,7 +386,7 @@ public sealed class LineageEvidencePackService : ILineageEvidencePackService
|
||||
dataLicense = "CC0-1.0",
|
||||
name = artifactDigest,
|
||||
documentNamespace = $"https://stellaops.io/spdx/{artifactDigest}",
|
||||
creationInfo = new { created = _timeProvider.GetUtcNow().ToString("O") },
|
||||
creationInfo = new { created = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture) },
|
||||
packages = Array.Empty<object>()
|
||||
}, JsonOptions);
|
||||
|
||||
@@ -420,7 +421,7 @@ public sealed class LineageEvidencePackService : ILineageEvidencePackService
|
||||
context = "https://openvex.dev/ns/v0.2.0",
|
||||
id = $"urn:stellaops:vex:{artifactDigest}",
|
||||
author = "StellaOps",
|
||||
timestamp = _timeProvider.GetUtcNow().ToString("O"),
|
||||
timestamp = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture),
|
||||
statements = Array.Empty<object>()
|
||||
}, JsonOptions);
|
||||
|
||||
@@ -459,7 +460,7 @@ public sealed class LineageEvidencePackService : ILineageEvidencePackService
|
||||
tenantId,
|
||||
verdict = "pass",
|
||||
policyVersion = "1.0.0",
|
||||
evaluatedAt = _timeProvider.GetUtcNow().ToString("O"),
|
||||
evaluatedAt = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture),
|
||||
rules = new { total = 0, passed = 0, failed = 0, warned = 0 }
|
||||
}, JsonOptions);
|
||||
|
||||
@@ -532,7 +533,7 @@ public sealed class LineageEvidencePackService : ILineageEvidencePackService
|
||||
|
||||
private string ComputeReplayHash(string artifactDigest, string sbomDigest, string merkleRoot)
|
||||
{
|
||||
var input = $"{artifactDigest}|{sbomDigest}|{merkleRoot}|{_timeProvider.GetUtcNow():O}";
|
||||
var input = $"{artifactDigest}|{sbomDigest}|{merkleRoot}|{_timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture)}";
|
||||
return $"sha256:{ComputeHash(input)}";
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit.v3" />
|
||||
<PackageReference Include="FluentAssertions" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -15,15 +16,17 @@ public sealed class AuditBundleJobHandler : IAuditBundleJobHandler
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, AuditBundleJob> _jobs = new();
|
||||
private readonly ILogger<AuditBundleJobHandler> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
public AuditBundleJobHandler(ILogger<AuditBundleJobHandler> logger)
|
||||
public AuditBundleJobHandler(ILogger<AuditBundleJobHandler> logger, TimeProvider? timeProvider = null)
|
||||
{
|
||||
_logger = logger;
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public Task<AuditBundleCreateResult> CreateBundleAsync(
|
||||
@@ -48,7 +51,7 @@ public sealed class AuditBundleJobHandler : IAuditBundleJobHandler
|
||||
}
|
||||
|
||||
var bundleId = $"bndl-{Guid.NewGuid():N}";
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var now = _timeProvider.GetUtcNow();
|
||||
|
||||
var job = new AuditBundleJob
|
||||
{
|
||||
@@ -246,7 +249,7 @@ public sealed class AuditBundleJobHandler : IAuditBundleJobHandler
|
||||
"stella.ops/v1",
|
||||
"AuditBundleIndex",
|
||||
job.BundleId,
|
||||
DateTimeOffset.UtcNow,
|
||||
_timeProvider.GetUtcNow(),
|
||||
job.CreatedBy,
|
||||
job.Subject,
|
||||
job.TimeWindow,
|
||||
@@ -271,7 +274,7 @@ public sealed class AuditBundleJobHandler : IAuditBundleJobHandler
|
||||
|
||||
job.Status = "Completed";
|
||||
job.Progress = 100;
|
||||
job.CompletedAt = DateTimeOffset.UtcNow;
|
||||
job.CompletedAt = _timeProvider.GetUtcNow();
|
||||
|
||||
_logger.LogInformation(
|
||||
"Completed audit bundle {BundleId} with hash {BundleHash}",
|
||||
@@ -286,12 +289,12 @@ public sealed class AuditBundleJobHandler : IAuditBundleJobHandler
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreateSampleVulnReport(BundleSubjectRefDto subject)
|
||||
private string CreateSampleVulnReport(BundleSubjectRefDto subject)
|
||||
{
|
||||
var report = new
|
||||
{
|
||||
subject = subject.Name,
|
||||
scanDate = DateTimeOffset.UtcNow.ToString("O"),
|
||||
scanDate = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture),
|
||||
findings = new[]
|
||||
{
|
||||
new { id = "CVE-2023-12345", severity = "HIGH", package = "sample-pkg", version = "1.0.0" }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.ExportCenter.Core.Domain;
|
||||
@@ -162,7 +163,7 @@ public sealed class ExportDistributionLifecycle : IExportDistributionLifecycle
|
||||
["location"] = location,
|
||||
["etag"] = etag,
|
||||
["versionId"] = versionId,
|
||||
["distributedAt"] = _timeProvider.GetUtcNow().ToString("O")
|
||||
["distributedAt"] = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture)
|
||||
};
|
||||
|
||||
return await UpdateDistributionStatusAsync(
|
||||
@@ -189,7 +190,7 @@ public sealed class ExportDistributionLifecycle : IExportDistributionLifecycle
|
||||
{
|
||||
["code"] = errorCode,
|
||||
["message"] = errorMessage,
|
||||
["timestamp"] = _timeProvider.GetUtcNow().ToString("O")
|
||||
["timestamp"] = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture)
|
||||
};
|
||||
|
||||
return await UpdateDistributionStatusAsync(
|
||||
@@ -231,7 +232,7 @@ public sealed class ExportDistributionLifecycle : IExportDistributionLifecycle
|
||||
|
||||
existingMetadata ??= new Dictionary<string, object?>();
|
||||
existingMetadata["verified"] = verified;
|
||||
existingMetadata["verifiedAt"] = now.ToString("O");
|
||||
existingMetadata["verifiedAt"] = now.ToString("O", CultureInfo.InvariantCulture);
|
||||
if (!string.IsNullOrEmpty(verificationDetails))
|
||||
{
|
||||
existingMetadata["verificationDetails"] = verificationDetails;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Cryptography;
|
||||
@@ -464,7 +465,7 @@ public sealed class OciDistributionClient : IOciDistributionClient
|
||||
{
|
||||
var annotations = new Dictionary<string, string>
|
||||
{
|
||||
[OciAnnotations.Created] = _timeProvider.GetUtcNow().ToString("O"),
|
||||
[OciAnnotations.Created] = _timeProvider.GetUtcNow().ToString("O", CultureInfo.InvariantCulture),
|
||||
[OciAnnotations.Vendor] = "StellaOps"
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -307,7 +308,7 @@ public sealed class SimulationReportExporter : ISimulationReportExporter
|
||||
yield return new SimulationExportLine
|
||||
{
|
||||
Type = "complete",
|
||||
Data = new { exported_at = now.ToString("O") }
|
||||
Data = new { exported_at = now.ToString("O", CultureInfo.InvariantCulture) }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user