Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/Fluxzy.Core/Archiving/ArchiveMetaInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using Fluxzy.Rules.Filters;

Expand Down Expand Up @@ -30,7 +31,7 @@ public class ArchiveMetaInformation
/// <summary>
/// Archive version
/// </summary>
public string ArchiveVersion { get; set; } = "0.2.0";
public string ArchiveVersion { get; set; } = "0.3.0";

/// <summary>
/// Information about the environment where the archive was created.
Expand All @@ -42,6 +43,23 @@ public class ArchiveMetaInformation
/// </summary>
public string FluxzyVersion { get; set; } = Assembly.GetExecutingAssembly().GetName().Version!.ToString();

/// <summary>
/// Snapshot of the <see cref="FluxzySetting"/> that was active when the archive was produced.
/// Sensitive fields (PKCS#12 password and file path, proxy authentication password,
/// certificate cache directory, user agent configuration file) are scrubbed before serialization.
/// When <see cref="FluxzySharedSetting.RedactSettingsInArchive"/> is true, alteration rules
/// and the save filter are also omitted.
/// Null on archives produced by Fluxzy &lt;= 0.2.0 and on archives produced by import engines.
/// </summary>
public FluxzySetting? CapturedSetting { get; set; }

/// <summary>
/// Endpoints the proxy was actually listening on once <c>Proxy.Run()</c> resolved them.
/// Differs from <see cref="FluxzySetting.BoundPoints"/> when a configured port of 0
/// was replaced by an OS-assigned ephemeral port.
/// </summary>
public List<IPEndPoint> ResolvedEndPoints { get; set; } = new();

/// <summary>
/// Can be used to store additional information about the archive.
/// </summary>
Expand Down
23 changes: 12 additions & 11 deletions src/Fluxzy.Core/Archiving/GlobalArchiveOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

namespace Fluxzy
{
/// <summary>
/// Provide serialization settings for producing default archive format
/// <summary>
/// Provide serialization settings for producing default archive format
/// </summary>
public static class GlobalArchiveOption
{
Expand All @@ -24,8 +24,8 @@ public static class GlobalArchiveOption
CompositeResolver.Create(new IMessagePackFormatter[] { new MessagePackAddressFormatter() },
new IFormatterResolver[] { StandardResolverAllowPrivate.Instance, ContractlessStandardResolver.Instance }));

/// <summary>
/// STJ default archive option
/// <summary>
/// STJ default archive option
/// </summary>
public static JsonSerializerOptions DefaultSerializerOptions { get; } = new() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Expand All @@ -37,13 +37,14 @@ public static class GlobalArchiveOption
new IpAddressConverter(),
new IpEndPointConverter(),
new PolymorphicConverter<Filter>(),
new PolymorphicConverter<Action>()
new PolymorphicConverter<Action>(),
new RedactingFluxzySettingConverter()
},
NumberHandling = JsonNumberHandling.AllowReadingFromString
};

/// <summary>
/// STJ default archive option for configuration file
/// <summary>
/// STJ default archive option for configuration file
/// </summary>
public static JsonSerializerOptions ConfigSerializerOptions { get; } = new() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Expand All @@ -61,8 +62,8 @@ public static class GlobalArchiveOption
NumberHandling = JsonNumberHandling.AllowReadingFromString
};

/// <summary>
/// HAR STJ archiving option, used by Har Packager
/// <summary>
/// HAR STJ archiving option, used by Har Packager
/// </summary>
public static JsonSerializerOptions HttpArchiveSerializerOptions { get; } = new() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Expand All @@ -76,8 +77,8 @@ public static class GlobalArchiveOption
};


/// <summary>
/// HAR STJ archiving option, used by Har Packager
/// <summary>
/// HAR STJ archiving option, used by Har Packager
/// </summary>
public static JsonSerializerOptions HttpArchivePrettySerializerOptions { get; } = new() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Expand Down
36 changes: 36 additions & 0 deletions src/Fluxzy.Core/Archiving/Readers/ArchiveMetaInformationReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2021 - Haga Rakotoharivelo - https://github.com/haga-rak

using System.Text.Json;
using System.Text.Json.Nodes;

namespace Fluxzy.Readers
{
internal static class ArchiveMetaInformationReader
{
/// <summary>
/// Deserializes a meta.json blob, falling back to a meta with a null
/// <see cref="ArchiveMetaInformation.CapturedSetting"/> when the embedded
/// setting can't be deserialized (e.g. a Filter/Action discriminator from a
/// newer plugin).
/// </summary>
public static ArchiveMetaInformation Read(byte[] bytes)
{
try {
return JsonSerializer.Deserialize<ArchiveMetaInformation>(bytes,
GlobalArchiveOption.DefaultSerializerOptions) ?? new ArchiveMetaInformation();
}
catch (JsonException) {
var node = JsonNode.Parse(bytes);

if (node is JsonObject obj && obj.ContainsKey("capturedSetting")) {
obj.Remove("capturedSetting");

return JsonSerializer.Deserialize<ArchiveMetaInformation>(obj.ToJsonString(),
GlobalArchiveOption.DefaultSerializerOptions) ?? new ArchiveMetaInformation();
}

throw;
}
}
}
}
6 changes: 2 additions & 4 deletions src/Fluxzy.Core/Archiving/Readers/DirectoryArchiveReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ public ArchiveMetaInformation ReadMetaInformation()
return new ArchiveMetaInformation();
}

using var metaStream = File.Open(metaPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

return JsonSerializer.Deserialize<ArchiveMetaInformation>(metaStream,
GlobalArchiveOption.DefaultSerializerOptions)!;
var bytes = File.ReadAllBytes(metaPath);
return ArchiveMetaInformationReader.Read(bytes);
}

public IEnumerable<ExchangeInfo> ReadAllExchanges()
Expand Down
5 changes: 3 additions & 2 deletions src/Fluxzy.Core/Archiving/Readers/FluxzyArchiveReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ public ArchiveMetaInformation ReadMetaInformation()
}

using var metaStream = metaEntry.Open();
using var ms = new MemoryStream();
metaStream.CopyTo(ms);

return JsonSerializer.Deserialize<ArchiveMetaInformation>(metaStream,
GlobalArchiveOption.DefaultSerializerOptions)!;
return ArchiveMetaInformationReader.Read(ms.ToArray());
}

public IEnumerable<ExchangeInfo> ReadAllExchanges()
Expand Down
32 changes: 29 additions & 3 deletions src/Fluxzy.Core/Archiving/Writers/DirectoryArchiveWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading;
Expand All @@ -16,10 +17,10 @@ namespace Fluxzy.Writers
{
public class DirectoryArchiveWriter : RealtimeArchiveWriter
{
private readonly ArchiveMetaInformation _archiveMetaInformation = CreateNewCaptureArchiveMetaInformation();
private readonly ArchiveMetaInformation _archiveMetaInformation;
private readonly object _metaLock = new object();

private static ArchiveMetaInformation CreateNewCaptureArchiveMetaInformation()
private static ArchiveMetaInformation CreateNewCaptureArchiveMetaInformation(FluxzySetting? capturedSetting)
{
var metaInformation = new ArchiveMetaInformation
{
Expand All @@ -31,12 +32,23 @@ private static ArchiveMetaInformation CreateNewCaptureArchiveMetaInformation()
"unknown",
#endif
FluxzySharedSetting.SkipCollectingEnvironmentInformation ? "" : Environment.MachineName
)
),
CapturedSetting = FreezeCapturedSetting(capturedSetting)
};

return metaInformation;
}

private static FluxzySetting? FreezeCapturedSetting(FluxzySetting? capturedSetting)
{
if (capturedSetting == null)
return null;

// Snapshot the live setting so subsequent mutations don't leak into persisted meta.
var json = JsonSerializer.Serialize(capturedSetting, GlobalArchiveOption.ConfigSerializerOptions);
return JsonSerializer.Deserialize<FluxzySetting>(json, GlobalArchiveOption.ConfigSerializerOptions);
}

private readonly string _archiveMetaInformationPath;
private readonly string _baseDirectory;
private readonly string _captureDirectory;
Expand All @@ -47,7 +59,13 @@ private static ArchiveMetaInformation CreateNewCaptureArchiveMetaInformation()
private readonly string _connectionDirectory;

public DirectoryArchiveWriter(string baseDirectory, Filter? saveFilter)
: this(baseDirectory, saveFilter, capturedSetting: null)
{
}

public DirectoryArchiveWriter(string baseDirectory, Filter? saveFilter, FluxzySetting? capturedSetting)
{
_archiveMetaInformation = CreateNewCaptureArchiveMetaInformation(capturedSetting);
_baseDirectory = baseDirectory;
_saveFilter = saveFilter;
_contentDirectory = Path.Combine(baseDirectory, "contents");
Expand All @@ -59,6 +77,14 @@ public DirectoryArchiveWriter(string baseDirectory, Filter? saveFilter)
_archiveMetaInformationPath = DirectoryArchiveHelper.GetMetaPath(baseDirectory);
}

public void SetResolvedEndPoints(IEnumerable<IPEndPoint> endPoints)
{
lock (_metaLock) {
_archiveMetaInformation.ResolvedEndPoints = endPoints.ToList();
UpdateMeta(true);
}
}

public override void Init()
{
base.Init();
Expand Down
11 changes: 11 additions & 0 deletions src/Fluxzy.Core/FluxzySharedSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ static FluxzySharedSetting()
SkipCollectingEnvironmentInformation =
Environment.GetEnvironmentVariable("SkipCollectingEnvironmentInformation") == "1";

RedactSettingsInArchive =
Environment.GetEnvironmentVariable("FLUXZY_REDACT_SETTINGS_IN_ARCHIVE") == "1";

if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("appdata"))) {
// for macOS and linux, this environment variable used in several temp file (certcache) is not
// set leading unwanted folder creation
Expand Down Expand Up @@ -52,6 +55,14 @@ static FluxzySharedSetting()
/// </summary>
public static bool SkipCollectingEnvironmentInformation { get; set; }

/// <summary>
/// When set to true, the FluxzySetting snapshot embedded in archive meta information will
/// omit alteration rules and the save filter (in addition to the always-on redaction of
/// credentials and local file paths). Settable via the FLUXZY_REDACT_SETTINGS_IN_ARCHIVE
/// environment variable.
/// </summary>
public static bool RedactSettingsInArchive { get; set; }

/// <summary>
/// </summary>
public static int DownStreamProviderReceiveTimeoutMilliseconds { get; } =
Expand Down
55 changes: 55 additions & 0 deletions src/Fluxzy.Core/Misc/Converters/RedactingFluxzySettingConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2021 - Haga Rakotoharivelo - https://github.com/haga-rak

using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace Fluxzy.Misc.Converters
{
/// <summary>
/// Serializes <see cref="FluxzySetting"/> for embedding in archive meta information,
/// scrubbing credentials and local file paths. Reading is delegated to the default
/// contract so consumers see a regular <see cref="FluxzySetting"/>.
/// </summary>
internal class RedactingFluxzySettingConverter : JsonConverter<FluxzySetting>
{
public override FluxzySetting? Read(ref Utf8JsonReader reader, System.Type typeToConvert, JsonSerializerOptions options)
{
return JsonSerializer.Deserialize<FluxzySetting>(ref reader, GlobalArchiveOption.ConfigSerializerOptions);
}

public override void Write(Utf8JsonWriter writer, FluxzySetting value, JsonSerializerOptions options)
{
var node = JsonSerializer.SerializeToNode(value, GlobalArchiveOption.ConfigSerializerOptions)?.AsObject();

if (node == null) {
writer.WriteNullValue();
return;
}

Redact(node);

node.WriteTo(writer);
}

private static void Redact(JsonObject root)
{
if (root["caCertificate"] is JsonObject cert) {
cert.Remove("pkcs12File");
cert.Remove("pkcs12Password");
}

if (root["proxyAuthentication"] is JsonObject auth) {
auth.Remove("password");
}

root.Remove("certificateCacheDirectory");
root.Remove("userAgentActionConfigurationFile");

if (FluxzySharedSetting.RedactSettingsInArchive) {
root.Remove("internalAlterationRules");
root.Remove("saveFilter");
}
}
}
}
6 changes: 5 additions & 1 deletion src/Fluxzy.Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public Proxy(
Directory.CreateDirectory(StartupSetting.ArchivingPolicy.Directory);

Writer = new DirectoryArchiveWriter(StartupSetting.ArchivingPolicy.Directory,
StartupSetting.SaveFilter);
StartupSetting.SaveFilter, StartupSetting);
}

if (StartupSetting.ArchivingPolicy.Type == ArchivingPolicyType.None) {
Expand Down Expand Up @@ -348,6 +348,10 @@ public IReadOnlyCollection<IPEndPoint> Run()

EndPoints = endPoints;

if (Writer is DirectoryArchiveWriter directoryWriter) {
directoryWriter.SetResolvedEndPoints(endPoints);
}

if (StartupSetting.EnableDiscoveryService) {
StartDiscoveryServices(endPoints);
}
Expand Down
Loading
Loading