Skip to content

Commit

Permalink
AutoWire detected proxies during setup (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mpdreamz authored Jul 10, 2023
1 parent 90fa59a commit b7c4dad
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Elastic.Elasticsearch.Ephemeral\Elastic.Elasticsearch.Ephemeral.csproj"/>
<ProjectReference Include="..\..\src\Elastic.Elasticsearch.Ephemeral\Elastic.Elasticsearch.Ephemeral.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Elastic.Transport" Version="0.4.12" />
</ItemGroup>

</Project>
19 changes: 19 additions & 0 deletions examples/Elastic.Ephemeral.Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
// See the LICENSE file in the project root for more information

using Elastic.Elasticsearch.Ephemeral;
using Elastic.Elasticsearch.Managed;
using Elastic.Transport;
using Elastic.Transport.Products.Elasticsearch;
using static Elastic.Elasticsearch.Ephemeral.ClusterAuthentication;
using static Elastic.Elasticsearch.Ephemeral.ClusterFeatures;
using HttpMethod = Elastic.Transport.HttpMethod;


var config = new EphemeralClusterConfiguration("8.7.0", XPack | Security | SSL);
Expand All @@ -16,4 +21,18 @@
exitEvent.Set();
};
using var started = cluster.Start();

var pool = new StaticNodePool(cluster.NodesUris());
var transportConfig = new TransportConfiguration(pool, productRegistration: ElasticsearchProductRegistration.Default)
.Authentication(new BasicAuthentication(Admin.Username, Admin.Password))
.ServerCertificateValidationCallback(CertificateValidations.AllowAll);
if (cluster.DetectedProxy != DetectedProxySoftware.None)
transportConfig = transportConfig.Proxy(new Uri("http://localhost:8080"), null!, null!);

var transport = new DefaultHttpTransport(transportConfig);

var response = await transport.RequestAsync<StringResponse>(HttpMethod.GET, "/");
Console.WriteLine(response);


exitEvent.WaitOne();
2 changes: 1 addition & 1 deletion examples/ScratchPad/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private static void ManualConfigRun()
var features = Security | XPack | SSL;
var config = new EphemeralClusterConfiguration(version, features, plugins, 1)
{
HttpFiddlerAware = true,
AutoWireKnownProxies = true,
ShowElasticsearchOutputAfterStarted = true,
CacheEsHomeInstallation = false,
TrialMode = XPackTrialMode.Trial,
Expand Down
2 changes: 1 addition & 1 deletion examples/ScratchPad/ValidateCombinations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static void Run()
Console.WriteLine($"{v} {f}");

Console.ForegroundColor = reset;
var config = new EphemeralClusterConfiguration(v, f, plugins, 1) {HttpFiddlerAware = true,};
var config = new EphemeralClusterConfiguration(v, f, plugins, 1) {AutoWireKnownProxies = true,};

using (var cluster = new EphemeralCluster(config))
try
Expand Down
10 changes: 7 additions & 3 deletions src/Elastic.Elasticsearch.Ephemeral/EphemeralCluster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ protected EphemeralCluster(TConfiguration clusterConfiguration) : base(clusterCo

public virtual ICollection<Uri> NodesUris(string hostName = null)
{
hostName = hostName ?? (ClusterConfiguration.HttpFiddlerAware && Process.GetProcessesByName("fiddler").Any()
? "ipv4.fiddler"
: "localhost");
hostName ??= "localhost";
if (hostName == "localhost" && ClusterConfiguration.AutoWireKnownProxies)
{
if (DetectedProxy == DetectedProxySoftware.Fiddler)
hostName = "ipv4.fiddler"; //magic reverse proxy address for fiddler
}

var ssl = ClusterConfiguration.EnableSsl ? "s" : "";
return Nodes
.Select(n => $"http{ssl}://{hostName}:{n.Port ?? 9200}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,14 @@ public EphemeralClusterConfiguration(ElasticVersion version, ClusterFeatures fea
/// </summary>
public XPackTrialMode TrialMode { get; set; }

/// <summary> Bootstrapping HTTP calls should attempt to auto route traffic through fiddler if its running </summary>
public bool HttpFiddlerAware { get; set; }
/// <summary>
/// Bootstrapping HTTP calls should attempt to auto route traffic through known proxy software if they are running
/// <list type="buller">
/// <item> <description>Fiddler, typically on Windows</description></item>
/// <item> <description>mitmproxy, typically on non Windows OS's</description></item>
/// </list>
/// </summary>
public bool AutoWireKnownProxies { get; set; }

protected virtual string NodePrefix => "ephemeral";

Expand Down
58 changes: 30 additions & 28 deletions src/Elastic.Elasticsearch.Ephemeral/Tasks/IClusterComposeTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Elastic.Elasticsearch.Managed;
using Elastic.Elasticsearch.Managed.ConsoleWriters;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
Expand Down Expand Up @@ -87,6 +88,9 @@ private HttpResponseMessage Call(
AutomaticDecompression =
DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None,
};
if (cluster.DetectedProxy != DetectedProxySoftware.None)
handler.Proxy = new WebProxy { Address = new Uri("http://localhost:8080") };

cluster.Writer.WriteDiagnostic(
$"{{{nameof(Call)}}} [{statusUrl}] SSL: {cluster.ClusterConfiguration.EnableSsl} Security: {cluster.ClusterConfiguration.EnableSecurity}");
if (cluster.ClusterConfiguration.EnableSsl)
Expand All @@ -98,39 +102,37 @@ private HttpResponseMessage Call(
#endif
}

using (var client = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(20)})
using var client = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(20)};
if (cluster.ClusterConfiguration.EnableSecurity)
{
if (cluster.ClusterConfiguration.EnableSecurity)
{
var byteArray =
Encoding.ASCII.GetBytes(
$"{ClusterAuthentication.Admin.Username}:{ClusterAuthentication.Admin.Password}");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}
var byteArray =
Encoding.ASCII.GetBytes(
$"{ClusterAuthentication.Admin.Username}:{ClusterAuthentication.Admin.Password}");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}

try
{
var response = verb(client, statusUrl, tokenSource.Token).ConfigureAwait(false).GetAwaiter()
.GetResult();
if (response.StatusCode == HttpStatusCode.OK) return response;
cluster.Writer.WriteDiagnostic(
$"{{{nameof(Call)}}} [{statusUrl}] Bad status code: [{(int) response.StatusCode}]");
var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
foreach (var l in (body ?? string.Empty).Split('\n', '\r'))
cluster.Writer.WriteDiagnostic($"{{{nameof(Call)}}} [{statusUrl}] returned [{l}]");
}
catch (Exception e)
{
cluster.Writer.WriteError($"{{{nameof(Call)}}} [{statusUrl}] exception: {e}");
// ignored
}
finally
{
try
{
var response = verb(client, statusUrl, tokenSource.Token).ConfigureAwait(false).GetAwaiter()
.GetResult();
if (response.StatusCode == HttpStatusCode.OK) return response;
cluster.Writer.WriteDiagnostic(
$"{{{nameof(Call)}}} [{statusUrl}] Bad status code: [{(int) response.StatusCode}]");
var body = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
foreach (var l in (body ?? string.Empty).Split('\n', '\r'))
cluster.Writer.WriteDiagnostic($"{{{nameof(Call)}}} [{statusUrl}] returned [{l}]");
}
catch (Exception e)
{
cluster.Writer.WriteError($"{{{nameof(Call)}}} [{statusUrl}] exception: {e}");
// ignored
}
finally
{
#if !NETSTANDARD
ServicePointManager.ServerCertificateValidationCallback -= ServerCertificateValidationCallback;
#endif
}
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ string F(ClusterFeatures feature)
cluster.Writer?.WriteDiagnostic(
$"{{{nameof(PrintConfiguration)}}} {{{nameof(c.SkipBuiltInAfterStartTasks)}}} [{c.SkipBuiltInAfterStartTasks}]");
cluster.Writer?.WriteDiagnostic(
$"{{{nameof(PrintConfiguration)}}} {{{nameof(c.HttpFiddlerAware)}}} [{c.HttpFiddlerAware}]");
$"{{{nameof(PrintConfiguration)}}} {{{nameof(c.AutoWireKnownProxies)}}} [{c.AutoWireKnownProxies}]");
cluster.Writer?.WriteDiagnostic(
$"{{{nameof(PrintConfiguration)}}} {{{nameof(c.NoCleanupAfterNodeStopped)}}} [{c.NoCleanupAfterNodeStopped}]");
}
Expand Down
17 changes: 17 additions & 0 deletions src/Elastic.Elasticsearch.Managed/ClusterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using Elastic.Elasticsearch.Managed.Configuration;
using Elastic.Elasticsearch.Managed.ConsoleWriters;
using Elastic.Elasticsearch.Managed.FileSystem;
using ProcNet.Std;
using static Elastic.Elasticsearch.Managed.DetectedProxySoftware;

namespace Elastic.Elasticsearch.Managed
{
Expand All @@ -30,6 +32,11 @@ public interface ICluster<out TConfiguration> : IDisposable
IDisposable Start(TimeSpan waitForStarted);

IDisposable Start(IConsoleLineHandler writer, TimeSpan waitForStarted);

/// <summary>
/// Whether known proxies were detected as running during startup
/// </summary>
DetectedProxySoftware DetectedProxy { get; }
}


Expand Down Expand Up @@ -75,8 +82,18 @@ NodeConfiguration Modify(NodeConfiguration n, int p)
node.NodeConfiguration.InitialMasterNodes(initialMasterNodes);

Nodes = new ReadOnlyCollection<ElasticsearchNode>(nodes);

if (Process.GetProcessesByName("fiddler").Any()) DetectedProxy = Fiddler;
else if (Process.GetProcessesByName("mitmproxy").Any()) DetectedProxy = MitmProxy;
else DetectedProxy = None;
}

/// <summary>
/// Whether known proxies were detected as running during startup
/// </summary>
public DetectedProxySoftware DetectedProxy { get; }


/// <summary>
/// A short name to identify the cluster defaults to the <see cref="ClusterBase" /> subclass name with Cluster
/// removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public ClusterConfiguration(ElasticVersion version, Func<ElasticVersion, string,
if (logsPathDefault != fs.LogsPath) Add("path.logs", fs.LogsPath);

if (version.Major < 6) Add("path.conf", fs.ConfigPath);

}

public Artifact Artifact { get; }
Expand Down
12 changes: 12 additions & 0 deletions src/Elastic.Elasticsearch.Managed/DetectedProxySoftware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

namespace Elastic.Elasticsearch.Managed;

public enum DetectedProxySoftware
{
None,
Fiddler,
MitmProxy
}

0 comments on commit b7c4dad

Please sign in to comment.