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

Ensure Elastic.Extensions.Logging can set auth through config #313

Merged
merged 1 commit into from
Jun 23, 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
1 change: 1 addition & 0 deletions ecs-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7610B796-BB3E-4CB2-8296-79BBFF6D23FC}"
ProjectSection(SolutionItems) = preProject
src\Directory.Build.props = src\Directory.Build.props
src\NullableExtensions.cs = src\NullableExtensions.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{3582B07D-C2B0-49CC-B676-EAF806EB010E}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<Description>Serilog TextFormatter that formats log events in accordance with Elastic Common Schema (ECS).</Description>
<IsPackable>True</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="Lib\UAParser.regexes.yaml" />
Expand All @@ -20,13 +21,12 @@
<ProjectReference Include="..\Elastic.CommonSchema\Elastic.CommonSchema.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="PolySharp" Version="1.13.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog" Version="2.9.0.0" />
<PackageReference Condition="$(DefineConstants.Contains(NETSTANDARD))" Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.1.0.0" />
<PackageReference Condition="$(DefineConstants.Contains(NETSTANDARD))" Include="Microsoft.AspNetCore.Http.Extensions" Version="2.1.0.0" />
<Reference Condition="$(DefineConstants.Contains(FULLFRAMEWORK))" Include="System.Web" />
<PackageReference Include="PolySharp" Version="1.13.2" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
11 changes: 7 additions & 4 deletions src/Elastic.Extensions.Logging/Elastic.Extensions.Logging.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@
<Title>Elasticsearch Logger Provider</Title>
<Description>Elasticsearch logger provider for Microsoft.Extensions.Logging. Writes direct to Elasticsearch using the Elastic Common Schema (ECS), with semantic logging of structured data from message and scope values, for use with the Elasticsearch-Logstash-Kibana (ELK) stack. The results can be viewed and queried in the Kibana console.</Description>
<PackageTags>Logging;LoggerProvider;Elasticsearch;ELK;Kibana;Logstash;Tracing;Diagnostics;Log;Trace;ECS</PackageTags>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
<IsPackable>True</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="2.1.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Elastic.CommonSchema\Elastic.CommonSchema.csproj" />
<ProjectReference Include="..\Elastic.Ingest.Elasticsearch.CommonSchema\Elastic.Ingest.Elasticsearch.CommonSchema.csproj" />
<PackageReference Include="PolySharp" Version="1.13.2" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<Compile Include="..\NullableExtensions.cs" />
</ItemGroup>

</Project>
39 changes: 33 additions & 6 deletions src/Elastic.Extensions.Logging/ElasticsearchLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,26 @@ private static NodePool CreateNodePool(ElasticsearchLoggerOptions loggerOptions)
return new StaticNodePool(nodeUris);
// case NodePoolType.StickySniffing:
case NodePoolType.Cloud:
if (!string.IsNullOrEmpty(shipTo.ApiKey))
if (shipTo.CloudId.IsNullOrEmpty())
throw new Exception($"Cloud {nameof(CloudNodePool)} requires '{nameof(ShipToOptions.CloudId)}' to be provided as well");

if (!shipTo.ApiKey.IsNullOrEmpty())
{
var apiKeyCredentials = new ApiKey(shipTo.ApiKey);
return new CloudNodePool(shipTo.CloudId, apiKeyCredentials);
}

var basicAuthCredentials = new BasicAuthentication(shipTo.Username, shipTo.Password);
return new CloudNodePool(shipTo.CloudId, basicAuthCredentials);
if (!shipTo.Username.IsNullOrEmpty() && !shipTo.Password.IsNullOrEmpty())
{
var basicAuthCredentials = new BasicAuthentication(shipTo.Username, shipTo.Password);
return new CloudNodePool(shipTo.CloudId, basicAuthCredentials);
}
throw new Exception(
$"Cloud requires either '{nameof(ShipToOptions.ApiKey)}' or"
+ $"'{nameof(ShipToOptions.Username)}' and '{nameof(ShipToOptions.Password)}"
);
default:
throw new ArgumentException($"Unrecognised connection pool type '{connectionPool}' specified in the configuration.", nameof(connectionPool));
throw new ArgumentException($"Unrecognised connection pool type '{connectionPool}' specified in the configuration.",
nameof(connectionPool));
}
}

Expand All @@ -120,12 +130,29 @@ private static HttpTransport CreateTransport(ElasticsearchLoggerOptions loggerOp
// TODO: Check if Uri has changed before recreating
// TODO: Injectable factory? Or some way of testing.
if (loggerOptions.Transport != null) return loggerOptions.Transport;

var connectionPool = CreateNodePool(loggerOptions);
var config = new TransportConfiguration(connectionPool, productRegistration: new ElasticsearchProductRegistration());
// Cloud sets authentication as required parameter in the constructor
if (loggerOptions.ShipTo.NodePoolType != NodePoolType.Cloud)
config = SetAuthenticationOnTransport(loggerOptions, config);

var transport = new DefaultHttpTransport<TransportConfiguration>(config);
return transport;
}

private static TransportConfiguration SetAuthenticationOnTransport(ElasticsearchLoggerOptions loggerOptions, TransportConfiguration config)
{
var apiKey = loggerOptions.ShipTo.ApiKey;
var username = loggerOptions.ShipTo.Username;
var password = loggerOptions.ShipTo.Password;
if (!username.IsNullOrEmpty() && !password.IsNullOrEmpty())
config = config.Authentication(new BasicAuthentication(username, password));
else if (!apiKey.IsNullOrEmpty())
config = config.Authentication(new ApiKey(apiKey));
return config;
}

private void ReloadShipper(ElasticsearchLoggerOptions loggerOptions)
{
var newShipper = CreatIngestChannel(loggerOptions);
Expand Down Expand Up @@ -157,7 +184,7 @@ private IBufferedChannel<LogEvent> CreatIngestChannel(ElasticsearchLoggerOptions
WriteEvent = async (stream, ctx, logEvent) => await logEvent.SerializeAsync(stream, ctx).ConfigureAwait(false),
};
SetupChannelOptions(_channelConfigurations, indexChannelOptions);
var channel = new EcsDataStreamChannel<LogEvent>(indexChannelOptions);
var channel = new EcsDataStreamChannel<LogEvent>(indexChannelOptions);
channel.BootstrapElasticsearch(loggerOptions.BootstrapMethod);
return channel;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Elastic.Extensions.Logging/Options/ShipToOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ public class ShipToOptions
/// <summary>
/// Gets or sets the API Key, where connection pool type is Cloud, and authenticating via API Key.
/// </summary>
public string ApiKey { get; set; } = "";
public string? ApiKey { get; set; }

/// <summary>
/// Gets or sets the cloud ID, where connection pool type is Cloud.
/// </summary>
public string CloudId { get; set; } = "";
public string? CloudId { get; set; }

/// <summary>
/// Gets or sets the connection pool type. Default for multiple nodes is <c>Sniffing</c>; other supported values are
Expand All @@ -36,11 +36,11 @@ public class ShipToOptions
/// <summary>
/// Gets or sets the password, where connection pool type is Cloud, and authenticating via username/password.
/// </summary>
public string Password { get; set; } = "";
public string? Password { get; set; } = "";

/// <summary>
/// Gets or sets the username, where connection pool type is Cloud, and authenticating via username/password.
/// </summary>
public string Username { get; set; } = "";
public string? Username { get; set; } = "";
}
}
7 changes: 7 additions & 0 deletions src/NullableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.Diagnostics.CodeAnalysis;

namespace System;
internal static class NullableStringExtensions {
internal static bool IsNullOrEmpty([NotNullWhen(false)] this string? data) =>
string.IsNullOrEmpty(data);
}