Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoWire detected proxies during setup #59

Merged
merged 2 commits into from
Jul 10, 2023
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
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
}