diff --git a/Directory.Build.targets b/Directory.Build.targets index 4f736399b..1edec76f9 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -49,6 +49,8 @@ + + \ No newline at end of file diff --git a/src/Moryx/Grpc/ClientConfig.cs b/src/Moryx/Grpc/ClientConfig.cs new file mode 100644 index 000000000..c81b26175 --- /dev/null +++ b/src/Moryx/Grpc/ClientConfig.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2025, Phoenix Contact GmbH & Co. KG +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace Moryx.Grpc; + +/// +/// Configuration for the gRPC client. +/// +public class ClientConfig +{ + /// + /// Host of the gRPC server + /// + /// localhost + /// 127.0.0.1 + [Description("Hostname of the gRPC server"), DefaultValue("localhost")] + public string Host { get; set; } + + /// + /// Hostname of the gRPC server + /// + /// 50021 + [Description("Port of the gRPC server"), DefaultValue(50021)] + public int Port { get; set; } + + + /// + /// Whether to use TLS or not + /// + [Description("Wheter to use TLS or not"), DefaultValue(true)] + public bool UseTls { get; set; } + + /// + /// Path to `.cert` file + /// + /// https://localhost:50021 + [Description("Path to `.crt` file, in case of TLS security"), DefaultValue("certificate.crt")] + public string CertPath { get; set; } +} \ No newline at end of file diff --git a/src/Moryx/Grpc/ClientConfigExtensions.cs b/src/Moryx/Grpc/ClientConfigExtensions.cs new file mode 100644 index 000000000..d78b47119 --- /dev/null +++ b/src/Moryx/Grpc/ClientConfigExtensions.cs @@ -0,0 +1,66 @@ + +using Grpc.Core; +using Grpc.Net.Client; +using System; +using System.Net.Http; + +namespace Moryx.Grpc +{ + /// + /// Extension methods for ClientConfig + /// + public static class ClientConfigExtensions + { + /// + /// With a given creates an Address/URL + /// + /// + /// + public static string CreateAddress(ClientConfig config) + { + var uriBuilder = new UriBuilder() + { + Host = config.Host, + Port = config.Port, + Scheme = config.UseTls ? "https" : "http" + }; + return uriBuilder.Uri.ToString(); + } + + /// + /// WIth a given creates a channel options + /// + /// + /// + public static GrpcChannelOptions CreateChannelOptions(ClientConfig config) + { + + if (config.UseTls) + { + // Make sure to use the certificate from the provided path + // Adding it to the (windows) certificates store did not work + // Maybe this can be improved in the future + var httpClientHandler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => + { +#if NET8_0_OR_GREATER + chain!.ChainPolicy.TrustMode = System.Security.Cryptography.X509Certificates.X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.CustomTrustStore.Add(new System.Security.Cryptography.X509Certificates.X509Certificate2(config.CertPath!)); +#endif + return chain.Build(cert!); + } + }; + return new GrpcChannelOptions + { + HttpHandler = httpClientHandler, + }; + } + + return new GrpcChannelOptions + { + Credentials = ChannelCredentials.Insecure, + }; + } + } +} diff --git a/src/Moryx/Moryx.csproj b/src/Moryx/Moryx.csproj index 9a2ea99dc..b443d9a05 100644 --- a/src/Moryx/Moryx.csproj +++ b/src/Moryx/Moryx.csproj @@ -15,7 +15,10 @@ - + + + +