Unverified Commit e1f3020f authored by Lemon's avatar Lemon Committed by GitHub

Add TLS and Token support (#63)

* Add TLS and Token support

* Add licenses

* Add TLS  support in Asp.Net
parent 3dd8451a
...@@ -9,8 +9,10 @@ namespace SkyWalking.Sample.AspNet.Controllers ...@@ -9,8 +9,10 @@ namespace SkyWalking.Sample.AspNet.Controllers
{ {
public async Task<IHttpActionResult> Get() public async Task<IHttpActionResult> Get()
{ {
var httpClient = new HttpClient(new HttpTracingHandler()); // var httpClient = new HttpClient(new HttpTracingHandler());
var values = await httpClient.GetStringAsync("http://localhost:5002/api/values"); // var values = await httpClient.GetStringAsync("http://localhost:5002/api/values");
var values = 1;
return Json(values); return Json(values);
} }
} }
......
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad">
<HintPath>..\..\packages\Grpc.Core.1.12.0\lib\net45\Grpc.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<HintPath>../..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> <HintPath>../..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
...@@ -43,6 +47,10 @@ ...@@ -43,6 +47,10 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263">
<HintPath>..\..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<HintPath>../..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath> <HintPath>../..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
...@@ -99,6 +107,13 @@ ...@@ -99,6 +107,13 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets" Condition="Exists('..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Grpc.Core.1.12.0\build\net45\Grpc.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="bootstrap" version="3.3.7" targetFramework="net45" /> <package id="bootstrap" version="3.3.7" targetFramework="net45" />
<package id="Grpc" version="1.12.0" targetFramework="net45" />
<package id="Grpc.Core" version="1.12.0" targetFramework="net45" />
<package id="jQuery" version="1.9.1" targetFramework="net45" /> <package id="jQuery" version="1.9.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
...@@ -11,4 +13,5 @@ ...@@ -11,4 +13,5 @@
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" /> <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" /> <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
...@@ -35,5 +35,9 @@ namespace SkyWalking.Config ...@@ -35,5 +35,9 @@ namespace SkyWalking.Config
/// Collector cluster:DirectServers="10.2.45.126:11800,10.2.45.127:11800" /// Collector cluster:DirectServers="10.2.45.126:11800,10.2.45.127:11800"
/// </summary> /// </summary>
public static string DirectServers { get; set; } public static string DirectServers { get; set; }
public static string Authentication { get; set; }
public static string CertificatePath { get; set; }
} }
} }
\ No newline at end of file
...@@ -55,5 +55,23 @@ namespace SkyWalking.AspNet ...@@ -55,5 +55,23 @@ namespace SkyWalking.AspNet
/// Zero or minus value means no limit. /// Zero or minus value means no limit.
/// </summary> /// </summary>
public int PendingSegmentsLimit { get; set; } = 300000; public int PendingSegmentsLimit { get; set; } = 300000;
/// <summary>
/// Set your own token to active auth
/// </summary>
public string Authentication
{
get;
set;
}
/// <summary>
/// Set certificate path to open ssl/tls
/// </summary>
public string CertificatePath
{
get;
set;
}
} }
} }
\ No newline at end of file
...@@ -48,6 +48,8 @@ namespace SkyWalking.AspNet ...@@ -48,6 +48,8 @@ namespace SkyWalking.AspNet
CollectorConfig.DirectServers = GetAppSetting(nameof(CollectorConfig.DirectServers), true); CollectorConfig.DirectServers = GetAppSetting(nameof(CollectorConfig.DirectServers), true);
AgentConfig.ApplicationCode = GetAppSetting(nameof(AgentConfig.ApplicationCode), true); AgentConfig.ApplicationCode = GetAppSetting(nameof(AgentConfig.ApplicationCode), true);
AgentConfig.Namespace = GetAppSetting(nameof(AgentConfig.Namespace), false); AgentConfig.Namespace = GetAppSetting(nameof(AgentConfig.Namespace), false);
CollectorConfig.CertificatePath = GetAppSetting(nameof(CollectorConfig.CertificatePath), false);
CollectorConfig.Authentication = GetAppSetting(nameof(CollectorConfig.Authentication), false);
var samplePer3Secs = GetAppSetting(nameof(AgentConfig.SamplePer3Secs), false); var samplePer3Secs = GetAppSetting(nameof(AgentConfig.SamplePer3Secs), false);
if (int.TryParse(samplePer3Secs, out var v)) if (int.TryParse(samplePer3Secs, out var v))
{ {
......
...@@ -55,6 +55,8 @@ namespace SkyWalking.AspNetCore ...@@ -55,6 +55,8 @@ namespace SkyWalking.AspNetCore
CollectorConfig.DirectServers = options.Value.DirectServers; CollectorConfig.DirectServers = options.Value.DirectServers;
AgentConfig.SamplePer3Secs = options.Value.SamplePer3Secs; AgentConfig.SamplePer3Secs = options.Value.SamplePer3Secs;
AgentConfig.PendingSegmentsLimit = options.Value.PendingSegmentsLimit; AgentConfig.PendingSegmentsLimit = options.Value.PendingSegmentsLimit;
CollectorConfig.Authentication = options.Value.Authentication;
CollectorConfig.CertificatePath = options.Value.CertificatePath;
_logger = LogManager.GetLogger<SkyWalkingHostedService>(); _logger = LogManager.GetLogger<SkyWalkingHostedService>();
_diagnosticObserver = diagnosticObserver; _diagnosticObserver = diagnosticObserver;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* *
*/ */
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace SkyWalking.AspNetCore namespace SkyWalking.AspNetCore
...@@ -70,5 +71,23 @@ namespace SkyWalking.AspNetCore ...@@ -70,5 +71,23 @@ namespace SkyWalking.AspNetCore
get; get;
set; set;
} = 300000; } = 300000;
/// <summary>
/// Set your own token to active auth
/// </summary>
public string Authentication
{
get;
set;
}
/// <summary>
/// Set certificate path to open ssl/tls
/// </summary>
public string CertificatePath
{
get;
set;
}
} }
} }
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using Grpc.Core;
using SkyWalking.Utils;
namespace SkyWalking.Remote.Authentication
{
internal static class AuthenticationInterceptors
{
private const string header = "authentication";
public static AsyncAuthInterceptor CreateAuthInterceptor(string token)
{
return (context, metadata) =>
{
var entry = CreateTokenHeader(token);
if (entry != null)
{
metadata.Add(entry);
}
return TaskUtils.CompletedTask;
};
}
private static Metadata.Entry CreateTokenHeader(string token)
{
return string.IsNullOrEmpty(token) ? null : new Metadata.Entry(header, token);
}
}
}
/*
* Licensed to the OpenSkywalking under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using Grpc.Core;
using SkyWalking.Remote.Authentication;
namespace SkyWalking.Remote
{
internal class GrpcChannelBuilder
{
private string _token;
private string _server;
private string _rootCertificatePath;
public GrpcChannelBuilder WithAuthenticationToken(string token)
{
_token = token;
return this;
}
public GrpcChannelBuilder WithServer(string server)
{
_server = server;
return this;
}
public GrpcChannelBuilder WithCredential(string rootCertificatePath)
{
_rootCertificatePath = rootCertificatePath;
return this;
}
public Channel Build()
{
return new Channel(_server, GetCredentials());
}
private ChannelCredentials GetCredentials()
{
if (_rootCertificatePath != null)
{
var authInterceptor = AuthenticationInterceptors.CreateAuthInterceptor(_token);
return ChannelCredentials.Create(new SslCredentials(), CallCredentials.FromInterceptor(authInterceptor));
}
return ChannelCredentials.Insecure;
}
}
}
...@@ -27,55 +27,55 @@ namespace SkyWalking.Remote ...@@ -27,55 +27,55 @@ namespace SkyWalking.Remote
{ {
private static readonly ILogger _logger = LogManager.GetLogger<GrpcConnection>(); private static readonly ILogger _logger = LogManager.GetLogger<GrpcConnection>();
private readonly Channel _internalChannel; public Channel GrpcChannel { get; }
private readonly string _server;
private GrpcConnectionState _state = GrpcConnectionState.Idle;
public Channel GrpcChannel => _internalChannel; public GrpcConnectionState State { get; private set; } = GrpcConnectionState.Idle;
public GrpcConnectionState State => _state; public string Server { get; }
public string Server => _server; public GrpcConnection(string server, string rootCertificatePath = null, string token = null)
public GrpcConnection(string server)
{ {
_server = server; Server = server;
_internalChannel = new Channel(server, ChannelCredentials.Insecure); GrpcChannel = new GrpcChannelBuilder()
.WithServer(server)
.WithCredential(rootCertificatePath)
.WithAuthenticationToken(token)
.Build();
} }
public async Task<bool> ConnectAsync(TimeSpan timeout) public async Task<bool> ConnectAsync(TimeSpan timeout)
{ {
if (_state == GrpcConnectionState.Ready) if (State == GrpcConnectionState.Ready)
{ {
return true; return true;
} }
_state = GrpcConnectionState.Connecting; State = GrpcConnectionState.Connecting;
try try
{ {
var deadLine = DateTime.UtcNow.AddSeconds(timeout.TotalSeconds); var deadLine = DateTime.UtcNow.AddSeconds(timeout.TotalSeconds);
await _internalChannel.ConnectAsync(deadLine); await GrpcChannel.ConnectAsync(deadLine);
_state = GrpcConnectionState.Ready; State = GrpcConnectionState.Ready;
_logger.Info($"Grpc channel connect success. [Server] = {_internalChannel.Target}"); _logger.Info($"Grpc channel connect success. [Server] = {GrpcChannel.Target}");
} }
catch (TaskCanceledException ex) catch (TaskCanceledException ex)
{ {
_state = GrpcConnectionState.Failure; State = GrpcConnectionState.Failure;
_logger.Warning($"Grpc channel connect timeout. {ex.Message}"); _logger.Warning($"Grpc channel connect timeout. {ex.Message}");
} }
catch (Exception ex) catch (Exception ex)
{ {
_state = GrpcConnectionState.Failure; State = GrpcConnectionState.Failure;
_logger.Warning($"Grpc channel connect fail. {ex.Message}"); _logger.Warning($"Grpc channel connect fail. {ex.Message}");
} }
return _state == GrpcConnectionState.Ready; return State == GrpcConnectionState.Ready;
} }
public async Task ShutdowmAsync() public async Task ShutdowmAsync()
{ {
try try
{ {
await _internalChannel.ShutdownAsync(); await GrpcChannel.ShutdownAsync();
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -83,25 +83,25 @@ namespace SkyWalking.Remote ...@@ -83,25 +83,25 @@ namespace SkyWalking.Remote
} }
finally finally
{ {
_state = GrpcConnectionState.Shutdown; State = GrpcConnectionState.Shutdown;
} }
} }
public bool CheckState() public bool CheckState()
{ {
return _state == GrpcConnectionState.Ready && _internalChannel.State == ChannelState.Ready; return State == GrpcConnectionState.Ready && GrpcChannel.State == ChannelState.Ready;
} }
public void Failure() public void Failure()
{ {
var currentState = _state; var currentState = State;
if (GrpcConnectionState.Ready == currentState) if (GrpcConnectionState.Ready == currentState)
{ {
_logger.Debug($"Grpc channel state changed. {_state} -> {_internalChannel.State}"); _logger.Debug($"Grpc channel state changed. {State} -> {GrpcChannel.State}");
} }
_state = GrpcConnectionState.Failure; State = GrpcConnectionState.Failure;
} }
} }
} }
\ No newline at end of file
...@@ -28,7 +28,7 @@ namespace SkyWalking.Remote ...@@ -28,7 +28,7 @@ namespace SkyWalking.Remote
public class GrpcConnectionManager public class GrpcConnectionManager
{ {
private static readonly ILogger _logger = LogManager.GetLogger<GrpcConnectionManager>(); private static readonly ILogger _logger = LogManager.GetLogger<GrpcConnectionManager>();
public const string NotFoundErrorMessage = "Not found available connection."; public const string NotFoundErrorMessage = "Not found available connection.";
public static GrpcConnectionManager Instance { get; } = new GrpcConnectionManager(); public static GrpcConnectionManager Instance { get; } = new GrpcConnectionManager();
...@@ -36,7 +36,7 @@ namespace SkyWalking.Remote ...@@ -36,7 +36,7 @@ namespace SkyWalking.Remote
private readonly Random _random = new Random(); private readonly Random _random = new Random();
private readonly AsyncLock _lock = new AsyncLock(); private readonly AsyncLock _lock = new AsyncLock();
private GrpcConnection _connection; private GrpcConnection _connection;
public bool Available => _connection != null && _connection.CheckState(); public bool Available => _connection != null && _connection.CheckState();
private GrpcConnectionManager() private GrpcConnectionManager()
...@@ -58,7 +58,8 @@ namespace SkyWalking.Remote ...@@ -58,7 +58,8 @@ namespace SkyWalking.Remote
await _connection.ShutdowmAsync(); await _connection.ShutdowmAsync();
} }
_connection = new GrpcConnection(GetServer(_connection?.Server)); var metadata = GetServerMetadata(_connection?.Server);
_connection = new GrpcConnection(metadata.Address, metadata.CertificatePath, metadata.Token);
await _connection.ConnectAsync(timeout); await _connection.ConnectAsync(timeout);
} }
} }
...@@ -76,11 +77,17 @@ namespace SkyWalking.Remote ...@@ -76,11 +77,17 @@ namespace SkyWalking.Remote
_logger.Debug(NotFoundErrorMessage); _logger.Debug(NotFoundErrorMessage);
return null; return null;
} }
return connection; return connection;
} }
private string GetServer(string currentServer) private ServerMetadata GetServerMetadata(string currentServer)
{
return new ServerMetadata(GetServerAddress(currentServer),
CollectorConfig.CertificatePath, CollectorConfig.Authentication);
}
private string GetServerAddress(string currentServer)
{ {
var servers = RemoteDownstreamConfig.Collector.gRPCServers.Distinct().ToArray(); var servers = RemoteDownstreamConfig.Collector.gRPCServers.Distinct().ToArray();
if (servers.Length == 1) if (servers.Length == 1)
...@@ -96,5 +103,21 @@ namespace SkyWalking.Remote ...@@ -96,5 +103,21 @@ namespace SkyWalking.Remote
var index = _random.Next() % servers.Length; var index = _random.Next() % servers.Length;
return servers[index]; return servers[index];
} }
public struct ServerMetadata
{
public string Address { get; }
public string Token { get; }
public string CertificatePath { get; }
public ServerMetadata(string address, string certificate, string token)
{
Address = address;
CertificatePath = certificate;
Token = token;
}
}
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment