Confused about the different certificate chains in staging

I'm not 100% familiar with all the concepts related to Certificate Chains, so please bear with me :slight_smile:

Long story short: I'd like to generate a staging certificate that is issued from a staging root CA cert that is not expired? Is that possible? If so, any suggestions?

Here's the full story:

My ultimate goal is to use Let's Encrypt Staging certificates to test a custom software command line tool.

I used jetstack/cert-manager in kubernetes to generate tls certificates for a nginx ingress. I configured a ClusterIssuer to use Let's Encrypt staging environment.

This worked great - I see that the certificates are provisioned and correctly associated to the ingress.

However, the custom cli tool that I'm testing is very picky (as expected). The certificate generated by the CertIssuer shows that it was issued by (STAGING) Doctored Durian Root CA X3, and because that certificate expired on 1/30/21, 9:01:15 AM EST, the cli tool (correctly) shows an error message of CERT_HAS_EXPIRED.

So far, so good, the custom cli is working as expected :white_check_mark:

But now, I'd like to prove that the cli tool can connect to staging cert if the root cert is not expired.

So, here's my question:

The certificate generated from Let's Encrypt appears to be Issued from the intermediate (STAGING) Artificial Apricot R3, which is issued from (STAGING) Doctored Durian Root CA X3

After reading thru this forum, I understand that there is an alternate chain that can be used? If I understand correctly, I think it should be possible to generate a cert issued from (STAGING) Pretend Pear X1 rather than from (STAGING) Doctored Durian Root CA X3?

I think it should be possible to configure the Preferred Chain ? But I'm not sure what value to set preferredChain to? I've found a few forum posts and tried a few values but none of them seemed to work.

So, ideally, I'd like to generate a staging certificate that is issued from a staging root CA cert that is not expired? Is that possible? If so, any suggestions?

Here's the yaml I use for the kubernetes Cert issuer:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-stage
spec:
  acme:
    # Prod: https://acme-v02.api.letsencrypt.org/directory
    # Staging:  https://acme-staging-v02.api.letsencrypt.org/directory
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    preferredChain: "??"
    # Email address used for ACME registration
    email: someone@somewhere.io
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-account-key
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx
          podTemplate:
            spec:
              nodeSelector:
                "kubernetes.io/os": linux

I think you've got the pieces figured out. I haven't tried it, but if staging is set up the way I expect, then you should be able to just set your preferred chain to (STAGING) Pretend Pear X1

5 Likes

That worked. I set preferredChain: "(STAGING) Pretend Pear X1", regenerated the certificate and now my certificate is issued by (STAGING) Artificial Apricot R3 which is issued by (STAGING) Pretend Pear X1 and all certs in the chain are valid (haven't expired).

Thanks!

3 Likes

All certs issued by STAGING R3 are issued by STAGING X1. There's a cross-sign for STAGING X1 to STAGING DST X3, which is used by default. ACME clients can be configured to use an alternate chain, but all that really does is leaving out the final cross-sign: You're still getting the same intermediate & leaf.

The staging chain mirrors the current production chain (which is also why there's an expired cross-sign root). The default chain is going to change next year, though your current setup should continue to work.

5 Likes

And I should have mentioned more about this: Most tools should actually be fine with the expired root, if they also have one of the non-expired certificates in the chain in its trust store. (Well, for staging none of them should be in the trust store by default of course, but for testing purposes you might be using it.) This has been a part of how the Web PKI is "supposed" to work for a while, which is why in production the cross-sign from the expired root is still being used and works for most use cases. So if you say a bit more about this tool and how you're configuring it, people here might be able to help you figure out how to configure it so that it would work regardless of which staging chain is being presented to it. (And how to do it in a corresponding way for production, assuming that you might be using the same sort of tool connecting to a system that uses a production cert.)

5 Likes

Thanks again @petercooperjr.

There are a few parts to the custom tools I'm testing.

The piece that is still unable to connect is an electron based desktop app. So my next step is to research how to configure an electron app to recognize non-standard staging certs. If anyone has useful links or advice on electron apps, that'd be great. I'll share here as well if I make progress.

1 Like

Certificate Chains bridge the gap between a Root and a Leaf/EndEntity Certificate.

The Roots are either trusted or untrusted. The Staging Certificates are untrusted, which means they are equivalent to self-signed certificates you can generate on the command line.

Using LetsEncrypt Staging Certificates may overcomplicate things for these needs. It may be easier to just generate your own self-signed root certificates and develop chains and leafs to the exact specifications you require.

Many test systems generate their own certs. The Pebble test server does this automatically on every invocation. I believe you must pre-configure this for the Boulder server.

5 Likes

And there is a document page to help Certificates for localhost - Let's Encrypt

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.