From ae142a14055e7361009b594a913255f60d3e0b7b Mon Sep 17 00:00:00 2001 From: Omer Tuchfeld Date: Thu, 10 Oct 2024 11:18:39 +0200 Subject: [PATCH] Support certs with `GeneralTime` # Background Recert until now only supported certs with asn1 `UTCTime` and not `GeneralizedTime`. # Problem When golang creates certs with expiration way out in the future, it uses `GeneralizedTime` instead of `UTCTime`. For example: ``` 4:d=2 hl=2 l= 13 prim: UTCTIME :240607174402Z 19:d=2 hl=2 l= 17 prim: UTCTIME :340605194402+0200 ``` vs ``` 4:d=2 hl=2 l= 13 prim: UTCTIME :240607174406Z 19:d=2 hl=2 l= 19 prim: GENERALIZEDTIME :21240514194406+0200 ``` Usually this is not a problem, because a typical OCP cluster doesn't have certs this far in the future, but eventually it will become a problem. Also RHOAI has a component (tektoncd) that has certs with expiry 100 years in the future [1] (despite the misleading name that says "Decade" rather than "Century"). Trying to recert a cluster with tektoncd will therefore lead to the following error: ``` error: |- scanning and recertification Caused by: 0: processing discovered objects 1: regenerating crypto 2: re-signing cert with subject CN=tekton-triggers-core-interceptors.openshift-pipelines.svc, O=knative.dev 3: mutating cert 4: extending expiration 5: forcefully expiring 6: evaluating current expiration 7: GeneralTime not supported ``` # Solution This PR adds support for asn1 generalized time in recert. It's simply a matter of casting the type correctly, the x509_certificate crate already supports it. # Testing This PR is untested, waiting for feedback from the user that reported the issue. [1] https://github.com/tektoncd/triggers/blob/59da11dd50424c9ccef883b558671e34efc0eba5/pkg/interceptors/server/server.go#L36 --- .../cert_key_pair/cert_mutations.rs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/cluster_crypto/cert_key_pair/cert_mutations.rs b/src/cluster_crypto/cert_key_pair/cert_mutations.rs index 7b45db01..b3c64cac 100644 --- a/src/cluster_crypto/cert_key_pair/cert_mutations.rs +++ b/src/cluster_crypto/cert_key_pair/cert_mutations.rs @@ -66,19 +66,16 @@ fn extend_certificate_expiration(tbs_certificate: &mut TbsCertificate) -> Result } fn get_certificate_expiration(tbs_certificate: &mut TbsCertificate) -> Result<(DateTime, DateTime)> { - let (current_not_before, current_not_after) = match &tbs_certificate.validity.not_before { - x509_certificate::asn1time::Time::UtcTime(not_before) => { - match &tbs_certificate.validity.not_after { - x509_certificate::asn1time::Time::UtcTime(not_after) => { - // Dereferencing is the only way to get a chrono::DateTime out of the - // x509_certificate::asn1time::UtcTime struct. - (*(not_before.clone()), *(not_after.clone())) - } - x509_certificate::asn1time::Time::GeneralTime(_) => bail!("GeneralTime not supported"), - } - } - x509_certificate::asn1time::Time::GeneralTime(_) => bail!("GeneralTime not supported"), + let current_not_before: DateTime = match &tbs_certificate.validity.not_before { + x509_certificate::asn1time::Time::UtcTime(not_before) => *(not_before.clone()), + x509_certificate::asn1time::Time::GeneralTime(not_before) => (*not_before).clone().into(), }; + + let current_not_after: DateTime = match &tbs_certificate.validity.not_after { + x509_certificate::asn1time::Time::UtcTime(not_after) => *(not_after.clone()), + x509_certificate::asn1time::Time::GeneralTime(not_after) => (*not_after).clone().into(), + }; + Ok((current_not_before, current_not_after)) }