Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Transport Layer Security (TLS) is a cryptographic protocol that secures network communication between Orleans silos and clients. Configure TLS to implement mutual authentication (mTLS) and encrypt data in transit, protecting your Orleans deployment from unauthorized access and eavesdropping.
Prerequisites
Before configuring TLS, ensure you have:
- An Orleans application with the Microsoft.Orleans.Server NuGet package installed for silos.
- The Microsoft.Orleans.Client NuGet package installed for clients.
- The Microsoft.Orleans.Connections.Security NuGet package installed for both silos and clients.
- A valid X.509 certificate for authentication, either in the Windows certificate store or as a file.
Tip
The accompanying SiloExample and ClientExample projects include a development-only startup path that creates temporary self-signed certificates so you can run the sample locally. The inline snippets below focus on the certificate store and certificate file patterns you would typically adapt for your own deployments.
Configure TLS on silos
To enable TLS on an Orleans silo, use the UseTls extension method. This method provides several overloads for different certificate configuration scenarios.
Basic TLS configuration
The following example shows how to configure TLS using a certificate from the Windows certificate store:
using IHost host = Host.CreateDefaultBuilder()
.UseOrleans(builder =>
{
builder
.UseLocalhostClustering()
.UseTls(StoreName.My, "my-certificate-subject", allowInvalid: false, StoreLocation.CurrentUser, options =>
{
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = "my-certificate-subject";
};
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
In the preceding code:
- The
StoreName.Myparameter specifies the certificate store location (Personal certificates). - The
"my-certificate-subject"parameter identifies the certificate by its subject name. - The
allowInvalid: falseparameter ensures that only valid certificates are accepted in production. - The
StoreLocation.CurrentUserparameter specifies the certificate store scope. - The
OnAuthenticateAsClientcallback sets theTargetHostfor outbound connections initiated by the silo.
Development environment configuration
For development and testing, you might need to use self-signed certificates. The following example shows how to configure TLS with relaxed validation for development:
var hostBuilder = Host.CreateDefaultBuilder()
.UseEnvironment(Environments.Development);
using IHost host = hostBuilder
.UseOrleans((context, builder) =>
{
var isDevelopment = context.HostingEnvironment.IsDevelopment();
builder
.UseLocalhostClustering()
.UseTls(StoreName.My, "localhost", allowInvalid: isDevelopment, StoreLocation.CurrentUser, options =>
{
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = "localhost";
};
if (isDevelopment)
{
options.AllowAnyRemoteCertificate();
}
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
In the preceding code:
- The
context.HostingEnvironment.IsDevelopment()method checks if the application is running in a development environment. - The AllowAnyRemoteCertificate method disables certificate validation in development.
Warning
Never use AllowAnyRemoteCertificate() or allowInvalid: true in production deployments. These settings disable important security checks and expose your application to security vulnerabilities.
Certificate file configuration
If you have a certificate file instead of using the certificate store, configure TLS as shown in the following example:
using var cert = X509CertificateLoader.LoadPkcs12FromFile("path/to/certificate.pfx", "password");
using IHost host = Host.CreateDefaultBuilder()
.UseOrleans(builder =>
{
builder
.UseLocalhostClustering()
.UseTls(cert, options =>
{
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = cert.GetNameInfo(X509NameType.DnsName, false) ?? "my-certificate-subject";
};
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
In the preceding code:
- The LoadPkcs12FromFile method loads a certificate from a PKCS#12 file (PFX format).
- The certificate is passed directly to the
UseTlsmethod.
Advanced TLS configuration
For production deployments, you might need more control over certificate selection and validation. The following example demonstrates advanced TLS configuration:
using IHost host = Host.CreateDefaultBuilder()
.UseOrleans(builder =>
{
builder
.UseLocalhostClustering()
.UseTls(StoreName.My, "my-certificate-subject", allowInvalid: false, StoreLocation.LocalMachine, options =>
{
options.LocalServerCertificateSelector = (connection, serverName) =>
{
using var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(
X509FindType.FindBySubjectName,
serverName ?? "my-certificate-subject",
validOnly: true);
return certificates.Count > 0 ? certificates[0] : null;
};
options.RemoteCertificateValidation = (certificate, chain, sslPolicyErrors) =>
sslPolicyErrors == SslPolicyErrors.None;
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = "my-certificate-subject";
};
options.CheckCertificateRevocation = true;
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
In the preceding code:
- The LocalServerCertificateSelector callback dynamically selects the appropriate server certificate.
- The RemoteCertificateValidation callback provides custom validation logic for remote certificates.
- The CheckCertificateRevocation property enables certificate revocation checking.
Configure TLS on clients
Orleans clients require similar TLS configuration to securely connect to TLS-enabled silos.
Basic client TLS configuration
The following example shows how to configure TLS on an Orleans client:
using IHost host = Host.CreateDefaultBuilder()
.UseOrleansClient(builder =>
{
builder
.UseLocalhostClustering()
.UseTls(StoreName.My, "my-certificate-subject", allowInvalid: false, StoreLocation.CurrentUser, options =>
{
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = "my-certificate-subject";
};
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
In the preceding code:
- The UseTls extension method configures TLS for the client.
- The OnAuthenticateAsClient callback configures client-side TLS options and sets the
TargetHostto match the server certificate name. - When you call
UseTlswith a client certificate, the client sends that certificate during the TLS handshake so the silo can enforce mutual TLS.
Development client configuration
For development environments, configure the client with relaxed validation as shown in the following example:
var hostBuilder = Host.CreateDefaultBuilder()
.UseEnvironment(Environments.Development);
using IHost host = hostBuilder
.UseOrleansClient((context, builder) =>
{
var isDevelopment = context.HostingEnvironment.IsDevelopment();
builder
.UseLocalhostClustering()
.UseTls(StoreName.My, "localhost", allowInvalid: isDevelopment, StoreLocation.CurrentUser, options =>
{
if (isDevelopment)
{
options.AllowAnyRemoteCertificate();
}
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = "localhost";
};
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
Certificate file client configuration
Configure a client using a certificate file as shown in the following example:
using var cert = X509CertificateLoader.LoadPkcs12FromFile("path/to/certificate.pfx", "password");
using IHost host = Host.CreateDefaultBuilder()
.UseOrleansClient(builder =>
{
builder
.UseLocalhostClustering()
.UseTls(cert, options =>
{
options.OnAuthenticateAsClient = (connection, sslOptions) =>
{
sslOptions.TargetHost = cert.GetNameInfo(X509NameType.DnsName, false) ?? "my-certificate-subject";
};
});
})
.ConfigureLogging(logging => logging.AddConsole())
.Build();
await host.RunAsync();
Best practices
Follow these best practices when configuring TLS in Orleans:
- Use the latest TLS protocol: Always prefer TLS 1.2 or TLS 1.3 for the strongest security. Avoid TLS 1.0 and TLS 1.1, which have known vulnerabilities.
- Let the OS choose the protocol version: Don't explicitly set TLS protocol versions in production code. Instead, defer to operating system defaults to automatically select the best protocol. Only explicitly set protocol versions if you have a specific compatibility requirement with legacy systems. When you explicitly set protocol versions, your application can't automatically benefit from newer protocols added in future OS updates.
- Validate certificates: Always validate certificate chains, expiration dates, and hostname matches in production. Never use
AllowAnyRemoteCertificate()or disable certificate validation outside of development environments. - Enable certificate revocation checking: Use CheckCertificateRevocation to verify that certificates haven't been revoked.
- Use strong certificates: Ensure your X.509 certificates use strong key lengths (at least 2048 bits for RSA) and are signed by a trusted Certificate Authority (CA).
- Secure certificate storage: Protect private keys with appropriate file permissions or by using hardware security modules (HSMs).
- Keep certificates current: Monitor certificate expiration dates and renew certificates before they expire.
- Keep software updated: Regularly update your .NET runtime and operating system to receive the latest security patches and protocol support.
For more information on .NET TLS best practices, see TLS/SSL best practices.