1
1
using System . Net ;
2
2
using System . Net . Security ;
3
+ using System . Security . Authentication ;
3
4
using System . Security . Cryptography . X509Certificates ;
4
5
using Microsoft . AspNetCore . Authentication . Certificate ;
6
+ using Microsoft . AspNetCore . Connections . Features ;
7
+ using Microsoft . AspNetCore . Http . Features ;
5
8
using Microsoft . AspNetCore . Server . HttpSys ;
6
9
using Microsoft . AspNetCore . Server . Kestrel . Core ;
7
10
using Microsoft . AspNetCore . Server . Kestrel . Https ;
8
11
9
12
var builder = WebApplication . CreateBuilder ( args ) ;
10
13
builder . Logging . ClearProviders ( ) ;
11
14
12
- var writeCertValidationEventsToConsole = bool . TryParse ( builder . Configuration [ "certValidationConsoleEnabled" ] , out var certValidationConsoleEnabled ) && certValidationConsoleEnabled ;
15
+ // behavioral
13
16
var mTlsEnabled = bool . TryParse ( builder . Configuration [ "mTLS" ] , out var mTlsEnabledConfig ) && mTlsEnabledConfig ;
14
17
var tlsRenegotiationEnabled = bool . TryParse ( builder . Configuration [ "tlsRenegotiation" ] , out var tlsRenegotiationEnabledConfig ) && tlsRenegotiationEnabledConfig ;
15
- var statsEnabled = bool . TryParse ( builder . Configuration [ "statsEnabled" ] , out var connectionStatsEnabledConfig ) && connectionStatsEnabledConfig ;
16
18
var listeningEndpoints = builder . Configuration [ "urls" ] ?? "https://localhost:5000/" ;
19
+ var supportedTlsVersions = ParseSslProtocols ( builder . Configuration [ "tlsProtocols" ] ) ;
20
+
21
+ // debug
22
+ var writeCertValidationEventsToConsole = bool . TryParse ( builder . Configuration [ "certValidationConsoleEnabled" ] , out var certValidationConsoleEnabled ) && certValidationConsoleEnabled ;
23
+ var statsEnabled = bool . TryParse ( builder . Configuration [ "statsEnabled" ] , out var connectionStatsEnabledConfig ) && connectionStatsEnabledConfig ;
24
+ var logRequestDetails = bool . TryParse ( builder . Configuration [ "logRequestDetails" ] , out var logRequestDetailsConfig ) && logRequestDetailsConfig ;
17
25
18
26
if ( mTlsEnabled && tlsRenegotiationEnabled )
19
27
{
@@ -40,6 +48,11 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
40
48
// [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
41
49
listenOptions . UseHttps ( "testCert.pfx" , "testPassword" , options =>
42
50
{
51
+ if ( supportedTlsVersions is not null )
52
+ {
53
+ options . SslProtocols = supportedTlsVersions . Value ;
54
+ }
55
+
43
56
if ( mTlsEnabled )
44
57
{
45
58
options . ClientCertificateMode = ClientCertificateMode . RequireCertificate ;
@@ -81,6 +94,28 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
81
94
return true ;
82
95
}
83
96
97
+ if ( logRequestDetails )
98
+ {
99
+ var logged = false ;
100
+ Console . WriteLine ( "Registered request details logging middleware" ) ;
101
+ app . Use ( async ( context , next ) =>
102
+ {
103
+ if ( ! logged )
104
+ {
105
+ logged = true ;
106
+
107
+ var tlsHandshakeFeature = context . Features . GetRequiredFeature < ITlsHandshakeFeature > ( ) ;
108
+
109
+ Console . WriteLine ( "Request details:" ) ;
110
+ Console . WriteLine ( "-----" ) ;
111
+ Console . WriteLine ( "TLS: " + tlsHandshakeFeature . Protocol ) ;
112
+ Console . WriteLine ( "-----" ) ;
113
+ }
114
+
115
+ await next ( context ) ;
116
+ } ) ;
117
+ }
118
+
84
119
if ( statsEnabled )
85
120
{
86
121
Console . WriteLine ( "Registered stats middleware" ) ;
@@ -89,7 +124,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
89
124
connectionIds . Add ( context . Connection . Id ) ;
90
125
Console . WriteLine ( $ "[stats] unique connections established: { connectionIds . Count } ; fetched certificates: { fetchedCertsCounter } ") ;
91
126
92
- await next ( ) ;
127
+ await next ( context ) ;
93
128
} ) ;
94
129
}
95
130
@@ -109,7 +144,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
109
144
Console . WriteLine ( $ "client certificate ({ clientCert . Thumbprint } ) already exists on the connection { context . Connection . Id } ") ;
110
145
}
111
146
112
- await next ( ) ;
147
+ await next ( context ) ;
113
148
} ) ;
114
149
}
115
150
@@ -137,6 +172,7 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
137
172
{
138
173
Console . WriteLine ( $ "\t enabled logging stats to console") ;
139
174
}
175
+ Console . WriteLine ( $ "\t supported TLS versions: { supportedTlsVersions } ") ;
140
176
Console . WriteLine ( $ "\t listening endpoints: { listeningEndpoints } ") ;
141
177
Console . WriteLine ( "--------------------------------" ) ;
142
178
@@ -157,4 +193,30 @@ static IPEndPoint CreateIPEndPoint(UrlPrefix urlPrefix)
157
193
}
158
194
159
195
return new IPEndPoint ( ip , urlPrefix . PortValue ) ;
196
+ }
197
+
198
+ static SslProtocols ? ParseSslProtocols ( string ? supportedTlsVersions )
199
+ {
200
+ var protocols = SslProtocols . None ;
201
+ if ( string . IsNullOrEmpty ( supportedTlsVersions ) || supportedTlsVersions == "any" )
202
+ {
203
+ return null ;
204
+ }
205
+
206
+ foreach ( var version in supportedTlsVersions . Split ( ',' ) )
207
+ {
208
+ switch ( version . Trim ( ) . ToLower ( ) )
209
+ {
210
+ case "tls12" :
211
+ protocols |= SslProtocols . Tls12 ;
212
+ break ;
213
+ case "tls13" :
214
+ protocols |= SslProtocols . Tls13 ;
215
+ break ;
216
+ default :
217
+ throw new ArgumentException ( $ "Unsupported TLS version: { version } ") ;
218
+ }
219
+ }
220
+
221
+ return protocols ;
160
222
}
0 commit comments