|  | 
| 3 | 3 | 
 | 
| 4 | 4 | #if NET8_0_OR_GREATER | 
| 5 | 5 | 
 | 
|  | 6 | +using Microsoft.Extensions.Configuration; | 
|  | 7 | + | 
| 6 | 8 | namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests; | 
| 7 | 9 | 
 | 
| 8 | 10 | public class OtlpMtlsCertificateManagerTests | 
| @@ -157,6 +159,165 @@ public void ValidateCertificateChain_ReturnsResult_WithValidCertificate() | 
| 157 | 159 |         Xunit.Assert.True(result || !result); | 
| 158 | 160 |     } | 
| 159 | 161 | 
 | 
|  | 162 | +    [Xunit.Fact] | 
|  | 163 | +    public void ValidateCertificateChain_UsesDefaultConfiguration_WhenConfigurationIsNull() | 
|  | 164 | +    { | 
|  | 165 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 166 | + | 
|  | 167 | +        // Both overloads should work | 
|  | 168 | +        var result1 = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate"); | 
|  | 169 | +        var result2 = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", null); | 
|  | 170 | + | 
|  | 171 | +        // Results should be the same since both use defaults | 
|  | 172 | +        Xunit.Assert.Equal(result1, result2); | 
|  | 173 | +    } | 
|  | 174 | + | 
|  | 175 | +    [Xunit.Fact] | 
|  | 176 | +    public void ValidateCertificateChain_UsesRevocationModeFromConfiguration() | 
|  | 177 | +    { | 
|  | 178 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 179 | + | 
|  | 180 | +        var configuration = new ConfigurationBuilder() | 
|  | 181 | +            .AddInMemoryCollection(new[] | 
|  | 182 | +            { | 
|  | 183 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationModeEnvVarName, "NoCheck"), | 
|  | 184 | +            }) | 
|  | 185 | +            .Build(); | 
|  | 186 | + | 
|  | 187 | +        // Should not throw when using NoCheck mode | 
|  | 188 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 189 | + | 
|  | 190 | +        // The method should execute without throwing | 
|  | 191 | +        Xunit.Assert.True(result || !result); | 
|  | 192 | +    } | 
|  | 193 | + | 
|  | 194 | +    [Xunit.Fact] | 
|  | 195 | +    public void ValidateCertificateChain_UsesRevocationFlagFromConfiguration() | 
|  | 196 | +    { | 
|  | 197 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 198 | + | 
|  | 199 | +        var configuration = new ConfigurationBuilder() | 
|  | 200 | +            .AddInMemoryCollection(new[] | 
|  | 201 | +            { | 
|  | 202 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationFlagEnvVarName, "EntireChain"), | 
|  | 203 | +            }) | 
|  | 204 | +            .Build(); | 
|  | 205 | + | 
|  | 206 | +        // Should not throw when using EntireChain flag | 
|  | 207 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 208 | + | 
|  | 209 | +        // The method should execute without throwing | 
|  | 210 | +        Xunit.Assert.True(result || !result); | 
|  | 211 | +    } | 
|  | 212 | + | 
|  | 213 | +    [Xunit.Fact] | 
|  | 214 | +    public void ValidateCertificateChain_UsesBothRevocationConfigurationValues() | 
|  | 215 | +    { | 
|  | 216 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 217 | + | 
|  | 218 | +        var configuration = new ConfigurationBuilder() | 
|  | 219 | +            .AddInMemoryCollection(new[] | 
|  | 220 | +            { | 
|  | 221 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationModeEnvVarName, "Offline"), | 
|  | 222 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationFlagEnvVarName, "EndCertificateOnly"), | 
|  | 223 | +            }) | 
|  | 224 | +            .Build(); | 
|  | 225 | + | 
|  | 226 | +        // Should not throw when using both configuration values | 
|  | 227 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 228 | + | 
|  | 229 | +        // The method should execute without throwing | 
|  | 230 | +        Xunit.Assert.True(result || !result); | 
|  | 231 | +    } | 
|  | 232 | + | 
|  | 233 | +    [Xunit.Fact] | 
|  | 234 | +    public void ValidateCertificateChain_UsesDefaultsForInvalidRevocationMode() | 
|  | 235 | +    { | 
|  | 236 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 237 | + | 
|  | 238 | +        var configuration = new ConfigurationBuilder() | 
|  | 239 | +            .AddInMemoryCollection(new[] | 
|  | 240 | +            { | 
|  | 241 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationModeEnvVarName, "InvalidMode"), | 
|  | 242 | +            }) | 
|  | 243 | +            .Build(); | 
|  | 244 | + | 
|  | 245 | +        // Should not throw even with invalid configuration value (should use default) | 
|  | 246 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 247 | + | 
|  | 248 | +        // The method should execute without throwing and use default Online mode | 
|  | 249 | +        Xunit.Assert.True(result || !result); | 
|  | 250 | +    } | 
|  | 251 | + | 
|  | 252 | +    [Xunit.Fact] | 
|  | 253 | +    public void ValidateCertificateChain_UsesDefaultsForInvalidRevocationFlag() | 
|  | 254 | +    { | 
|  | 255 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 256 | + | 
|  | 257 | +        var configuration = new ConfigurationBuilder() | 
|  | 258 | +            .AddInMemoryCollection(new[] | 
|  | 259 | +            { | 
|  | 260 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationFlagEnvVarName, "InvalidFlag"), | 
|  | 261 | +            }) | 
|  | 262 | +            .Build(); | 
|  | 263 | + | 
|  | 264 | +        // Should not throw even with invalid configuration value (should use default) | 
|  | 265 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 266 | + | 
|  | 267 | +        // The method should execute without throwing and use default ExcludeRoot flag | 
|  | 268 | +        Xunit.Assert.True(result || !result); | 
|  | 269 | +    } | 
|  | 270 | + | 
|  | 271 | +    [Xunit.Theory] | 
|  | 272 | +    [Xunit.InlineData("Online")] | 
|  | 273 | +    [Xunit.InlineData("Offline")] | 
|  | 274 | +    [Xunit.InlineData("NoCheck")] | 
|  | 275 | +    [Xunit.InlineData("online")] | 
|  | 276 | +    [Xunit.InlineData("OFFLINE")] | 
|  | 277 | +    [Xunit.InlineData("nocheck")] | 
|  | 278 | +    public void ValidateCertificateChain_HandlesCaseInsensitiveRevocationMode(string revocationMode) | 
|  | 279 | +    { | 
|  | 280 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 281 | + | 
|  | 282 | +        var configuration = new ConfigurationBuilder() | 
|  | 283 | +            .AddInMemoryCollection(new[] | 
|  | 284 | +            { | 
|  | 285 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationModeEnvVarName, revocationMode), | 
|  | 286 | +            }) | 
|  | 287 | +            .Build(); | 
|  | 288 | + | 
|  | 289 | +        // Should handle case-insensitive enum parsing | 
|  | 290 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 291 | + | 
|  | 292 | +        // The method should execute without throwing | 
|  | 293 | +        Xunit.Assert.True(result || !result); | 
|  | 294 | +    } | 
|  | 295 | + | 
|  | 296 | +    [Xunit.Theory] | 
|  | 297 | +    [Xunit.InlineData("ExcludeRoot")] | 
|  | 298 | +    [Xunit.InlineData("EntireChain")] | 
|  | 299 | +    [Xunit.InlineData("EndCertificateOnly")] | 
|  | 300 | +    [Xunit.InlineData("excluderoot")] | 
|  | 301 | +    [Xunit.InlineData("ENTIRECHAIN")] | 
|  | 302 | +    [Xunit.InlineData("endcertificateonly")] | 
|  | 303 | +    public void ValidateCertificateChain_HandlesCaseInsensitiveRevocationFlag(string revocationFlag) | 
|  | 304 | +    { | 
|  | 305 | +        using var cert = CreateSelfSignedCertificate(); | 
|  | 306 | + | 
|  | 307 | +        var configuration = new ConfigurationBuilder() | 
|  | 308 | +            .AddInMemoryCollection(new[] | 
|  | 309 | +            { | 
|  | 310 | +                new KeyValuePair<string, string?>(OtlpSpecConfigDefinitions.CertificateRevocationFlagEnvVarName, revocationFlag), | 
|  | 311 | +            }) | 
|  | 312 | +            .Build(); | 
|  | 313 | + | 
|  | 314 | +        // Should handle case-insensitive enum parsing | 
|  | 315 | +        var result = OpenTelemetryProtocol.Implementation.OtlpMtlsCertificateManager.ValidateCertificateChain(cert, "test certificate", configuration); | 
|  | 316 | + | 
|  | 317 | +        // The method should execute without throwing | 
|  | 318 | +        Xunit.Assert.True(result || !result); | 
|  | 319 | +    } | 
|  | 320 | + | 
| 160 | 321 |     private static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSignedCertificate() | 
| 161 | 322 |     { | 
| 162 | 323 |         using var rsa = System.Security.Cryptography.RSA.Create(2048); | 
|  | 
0 commit comments