-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Switch to dynamic cert gen for tests #39685
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
Conversation
Hey @bartonjs I finally got around to trying the snippet you suggested for us to dynamically generate certs in: #32806 (comment) Everything seems mostly fine except for one case where Ubuntu is seeming to allow an expired self signed cert: https://dev.azure.com/dnceng/public/_build/results?buildId=1566042&view=ms.vss-test-web.build-test-results-tab&runId=44083042&resultId=106439&paneView=debug This seems weird as its not failing on Mac or Windows, are there any known issues with these apis on linux? I'm also not sure if the old cert matches exactly what the new cert does, does passing in no/null eku end up creating a cert with both client/server eku? I guess we have always had issues on ubuntu, since there's another test that was already disabled:
|
/azp run |
Azure Pipelines successfully started running 3 pipeline(s). |
Except for specific specs that say otherwise (such as RFC 3161 trusted timestamping), a cert that has no EKU extension is treated as supporting all usages. Since TLS doesn't have such a disclaimer, yes, a cert with no EKU extension at all is valid as both a client cert and a server cert
Weird. We certainly have a lot of expiration related tests in X509Chain, and I can't think of anywhere that we'd have a behavior like that. |
SignedClient = MakeCert( | ||
"CN=Valid Signed Client,OU=dev,DC=idunno-dev,DC=org", | ||
ClientEku, | ||
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.
From the name, and usage, I'd expect that SignedClient is supposed to be issued by SelfSignedPrimaryRoot (or maybe SelfSignedSecondaryRoot?). But it's just another self-signed cert.
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.
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.
No. You'll have to, for this cert, replace return request.CreateSelfSigned(notBefore, notAfter);
Span<byte> serial = stackalloc byte[19];
RandomNumberGenerator.Fill(serial);
using (X509Certificate2 pubOnly = request.Create(SelfSignedSecondaryRoot, notBefore, notAfter, serial))
{
return pubOnly.CopyWithPrivateKey(key);
}
So, something like
private static X509Certificate2 MakeCert(
string subjectName,
string eku,
DateTimeOffset notBefore,
DateTimeOffset notAfter,
X509Certificate2 issuerCert = null)
{
using (var key = RSA.Create(2048))
{
CertificateRequest request = new CertificateRequest(
subjectName,
key,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
if (eku != null)
{
request.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection { new Oid(eku, null) }, false));
}
if (issuerCert == null)
{
return request.CreateSelfSigned(notBefore, notAfter);
}
else
{
Span<byte> serial = stackalloc byte[19];
RandomNumberGenerator.Fill(serial);
using (X509Certificate2 pubOnly = request.Create(SelfSignedSecondaryRoot, notBefore, notAfter, serial))
{
return pubOnly.CopyWithPrivateKey(key);
}
}
}
But you'll have to also create SelfSignedSecondaryRoot as a valid CA cert. (An X509BasicConstraintsExtension where isCa is true, and the key usages needs to include cert signing)
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.
Ok I will give that a shot, but this leads me to ask, are we missing some tests to exercise these kinds of subtle cert differences, or it doesn't really matter to us since at our layer we are just passing the certs. Basically if no tests fail without the issuer in the old cert, maybe we should either add tests to verify this, or don't bother specifying it... cc @blowdart for his thoughts as well
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.
I mean obviously switch away from my old cert names :)
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.
Well... none of your certs here have valid CN/SAN entries to be used as a TLS server, so there is clearly some custom validation going on wherever these certs are used. I don't see where it's happening, so it's hard to say what's what.
aspnetcore/src/Security/Authentication/test/CertificateTests.cs
Lines 347 to 361 in a5ac61c
public async Task VerifyValidClientCertWithAdditionalCertificatesAuthenticates() | |
{ | |
using var host = await CreateHost( | |
new CertificateAuthenticationOptions | |
{ | |
Events = successfulValidationEvents, | |
ChainTrustValidationMode = X509ChainTrustMode.CustomRootTrust, | |
CustomTrustStore = new X509Certificate2Collection() { Certificates.SelfSignedPrimaryRoot, }, | |
AdditionalChainCertificates = new X509Certificate2Collection() { Certificates.SignedSecondaryRoot }, | |
RevocationMode = X509RevocationMode.NoCheck | |
}, Certificates.SignedClient); | |
using var server = host.GetTestServer(); | |
var response = await server.CreateClient().GetAsync("https://example.com/"); | |
Assert.Equal(HttpStatusCode.OK, response.StatusCode); |
certainly looks like it should have failed in your current configuration (and the current configuration with checked-in certs... unless SelfSignedSecondaryRoot is actually a child issuing authority of SelfSignedPrimaryRoot?). It feels like it should only pass when the server cert chains up to SelfSignedPrimaryRoot.
Of course, that test is disabled, but should presumably have had the Skip removed in this PR since it's addressing the issue of expired certs.
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.
Right, for some reason only VerifyExpiredSelfSignedFails and VerifyNotYetValidSelfSignedFails fail but only on Ubuntu right now
This gets us most of the way there by deleting the certs, there's still some tests skipped on ubuntu and mac, but we don't have any specific platform code that we need to worry about (and the tests are already skipped today) so this is still an improvement |
* [release/6.0] Switch to dynamic cert gen for tests - Cherry-picked from #39685 * Remove non-existing project from AspNetCore.sln * Log ClientCertificateAuthenticationTests --------- Co-authored-by: Hao Kung <HaoK@users.noreply.github.com>
Fixes #32813 and should get us out of the business of expiring test certs
Will address the more complicated cert chain in a later PR (most likely next build ops) that's already tracked via #39669