-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(remote): implement mutual TLS authentication support #7851
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
feat(remote): implement mutual TLS authentication support #7851
Conversation
Implements mutual TLS (mTLS) authentication as a defense-in-depth security measure for Akka.Remote TLS connections. When enabled, both client and server must present valid certificates with accessible private keys during the TLS handshake, ensuring symmetric authentication. Key Changes: - Add require-mutual-authentication config option (default: true) - Update SslSettings to include RequireMutualAuthentication property - Modify client TLS handler to provide certificate only when mutual TLS enabled - Modify server TLS handler to require and validate client certificates when enabled - Add comprehensive test suite for mutual TLS scenarios Security Benefits: - Prevents nodes with inaccessible private keys from connecting as clients - Ensures complete bidirectional authentication (not just server-side) - Works in conjunction with startup certificate validation for fail-fast behavior - Provides defense-in-depth security for production deployments Configuration: akka.remote.dot-netty.tcp.ssl { require-mutual-authentication = true # Default: secure by default } Set to false only if your environment cannot support client certificate authentication. Related: Freshdesk akkadotnet#538 - TLS certificate private key validation
Major overhaul of the security documentation to reflect new TLS features and provide comprehensive security guidance for production deployments. Changes: - Document new startup certificate validation feature (v1.5.52+) - Document new mutual TLS authentication support (v1.5.52+) - Add detailed suppress-validation guidance with security implications - Provide Windows Certificate Store configuration examples - Include PowerShell scripts for certificate management - Add troubleshooting section for common TLS issues - Update configuration examples from insecure to secure defaults - Fix deprecated external links (Microsoft Learn, IETF, OWASP) - Add security analysis for different configuration levels - Include migration guide for upgrading to mutual TLS - Add best practices summary with 10 key recommendations - Document common pitfalls and their solutions Security improvements: - Changed example configs to use suppress-validation = false by default - Added warnings about using suppress-validation = true in production - Emphasized defense-in-depth with VPNs + TLS + mutual TLS - Documented proper self-signed certificate usage for development The documentation now provides clear guidance on: - What TLS protects against (and what it doesn't) - When to use mutual TLS vs standard TLS - How to properly configure certificates in production - How to troubleshoot common certificate permission issues Related: Freshdesk akkadotnet#538 - TLS certificate validation improvements
- Create TlsConfigurationSample.cs with proper HOCON configuration examples - Update security.md to reference code samples using DocFX syntax - Add context explaining when TLS is needed vs optional - Remove poorly designed region tags from test file The documentation now follows Akka.NET documentation guidelines with proper code references instead of inline configuration blocks.
Added configurable mutual TLS (mTLS) authentication for Akka.Remote to provide bidirectional certificate validation between client and server nodes. This feature enhances security by ensuring both sides of a connection authenticate with valid certificates. Changes: - Added `require-mutual-authentication` config option (defaults to true for security-by-default) - Updated DotNettyTransport to enforce mutual TLS in both client and server pipelines - Added comprehensive test suite for mutual TLS scenarios - Updated security documentation with detailed TLS/mTLS configuration guidance - Added code samples for various TLS configurations (standard, mutual, Windows cert store) - Included Mermaid sequence diagrams for TLS vs mTLS flows (pending Mermaid support on site) The implementation ensures backward compatibility while encouraging secure defaults. When mutual TLS is disabled, the system falls back to standard server-only authentication. Related to Freshdesk ticket akkadotnet#538
- Fixed all heading title case to comply with markdownlint-rule-titlecase - Changed 'suppress-validation' to 'Suppress-Validation' in headings - Fixed error message headings to use proper title case - All CI/CD checks should now pass
Added VPN provider names to the accepted words list to fix CI spellcheck failures
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detailed my changes - found some things especially around the tests that need to be improved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modernized the documentation quite a bit, but I'll need to do another PR that adds Mermaid support in order to get the handshake diagram to work.
Worth noting: the new Quic transports in Akka.NET v1.6 will, 100% always require a certificate in order to work. That is baked into how Quic works and is an unavoidable requirement.
# | ||
# Set to false only if your environment cannot support client certificate authentication. | ||
# Default: true (secure by default) | ||
require-mutual-authentication = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New mutual TLS requirement - this is technically a breaking behavioral change, but it closes a real security vulnerability so it has to be done.
/// When require-mutual-authentication is enabled, both client and server must | ||
/// present valid certificates with accessible private keys. | ||
/// </summary> | ||
public class DotNettyMutualTlsSpec : AkkaSpec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default SSL / TLS specs already cover the happy path scenario - we should rewrite this to ensure hard fail if the two different, but valid certificates are used - and maybe another scenario where the same certificate is used but the password / private key auth is incorrect on one of the nodes.
} | ||
|
||
public SslSettings(X509Certificate2 certificate, bool suppressValidation) | ||
public SslSettings(X509Certificate2 certificate, bool suppressValidation, bool requireMutualAuthentication = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically a breaking binary signature change - maybe I can fix that.
- Fixed binary compatibility by adding overloaded SslSettings constructor - Added config test to verify RequireMutualAuthentication defaults to true - Added test for mutual TLS failure when client has no certificate - Added test to verify mutual TLS can be disabled for backward compatibility - Enhanced DotNettyMutualTlsSpec with more comprehensive test scenarios
…aronontheweb/akka.net into feature/mutual-tls-enforcement
- Generated new self-signed certificate (akka-client-cert.pfx) for testing - Modified CreateConfig to accept custom certificate paths - Added test to verify mutual TLS fails when client and server have different valid certificates - This ensures proper certificate validation in mutual TLS mode
- Generated new self-signed certificate (akka-client-cert.pfx) to test scenarios where client and server have different valid certificates - Added certificate to project file as build output - Force-added certificate to git (normally ignored by .gitignore)
- Added new test SSL_should_have_secure_defaults_when_enabled to verify secure defaults when SSL is enabled - Removed SSL checks from non-SSL test Remoting_should_contain_correct_heliosTCP_values_in_ReferenceConf - Fixed certificate path resolution using full path - Tests now properly verify that require-mutual-authentication defaults to true and suppress-validation defaults to false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a second cert to TLS verification specs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have one more commit coming that removes a bunch of duplicate tests that all cover the same functionality, but otherwise this is complete and I'm satisfied with it.
/// </summary> | ||
public class DotNettyMutualTlsSpec : AkkaSpec | ||
{ | ||
private const string ValidCertPath = "Resources/akka-validcert.pfx"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two different certs now.
try | ||
{ | ||
// Server with mutual TLS using the original certificate | ||
var serverConfig = CreateConfig(enableSsl: true, requireMutualAuth: true, suppressValidation: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a different cert than the client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fails with
[SERVER] [WARNING][10/03/2025 16:59:40.547Z][Thread 0033][TcpTransport (akka://ServerSystem)] Mutual TLS: Client certificate validation failed with errors: RemoteCertificateChainErrors
[SERVER] [ERROR][10/03/2025 16:59:40.548Z][Thread 0054][TcpServerHandler (akka://ServerSystem)] TLS handshake failed. Channel [[::ffff:127.0.0.1]:56636->[::ffff:127.0.0.1]:56638](Id=1c17f0a0)
Cause: System.AggregateException: One or more errors occurred. (The remote certificate was rejected by the provided RemoteCertificateValidationCallback.)
---> System.Security.Authentication.AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.
at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
- Restored DotNettySslSetupSpec which tests SSL configuration via Setup API - This is distinct from HOCON-based configuration tested in DotNettySslSupportSpec - Added test for configuring mutual TLS via DotNettySslSetup - Enhanced TestActorSystemSetup to support mutual authentication parameter
- Removed unsupported requireMutualAuth parameter from DotNettySslSetup constructor - Updated test to combine Setup API certificate with HOCON mutual TLS configuration - Fixed shutdown method call to use correct API
This reverts commit 6503391.
This reverts commit b23c3cd.
This reverts commit 7a7f3ca.
There are some redundant tests we should clean up later, but that's not needed for now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Summary
require-mutual-authentication = true
Changes
Implementation
require-mutual-authentication
configuration option to Remote.conf (defaults to true)SslSettings
class to includeRequireMutualAuthentication
propertyDotNettyTransport.cs
to enforce mutual TLS in both client and server pipelines:DotNettyMutualTlsSpec.cs
test suite covering:Documentation
TlsConfigurationSample.cs
with DocFX-compatible code regions for:Security Improvements
require-mutual-authentication = true
by default when SSL is enabledBackward Compatibility
require-mutual-authentication = false
Related Issues
Test Plan