Workflow for using alternate link relation

Regarding https://community.letsencrypt.org/t/transition-to-isrgs-root-delayed-until-sep-29/125516: could someone describe the workflow when using the alternate link relation to retrieve certificates that are cross-signed with IdenTrust’s DST Root X3? Which call returns the link(s) in the header and what will the alternate link return to my client when I call it?

1 Like

The workflow is exactly as before. Once this feature is enabled in Boulder, you should be able to use it. If you want to develop support for it, you can use Pebble; see the documentation: https://github.com/letsencrypt/pebble/#ca-root-and-intermediate-certificates

If you export PEBBLE_ALTERNATE_ROOTS=2 (or a larger integer) before starting Pebble, the alternative link headers will be sent. To pick out the correct certificate, you have to see by which root the intermediate you got has been signed with.

3 Likes

FYI the feature is now enabled in both staging in production.

Certbot is the only client I know so far that has implemented the chain selection, you can check out how it was implemented in my PR here: https://github.com/certbot/certbot/pull/8080

Staging roots:

  • Fake LE Root X1 (default)
  • Fake LE Root X2

Production roots:

  • DST Root CA X3 (default)
  • ISRG Root X1

Test drive the functionality with:

certbot certonly --staging --preferred-chain "Fake LE Root X2" -d example.com

To apply a change globally for future renewals, you can add it to one of the cli.ini locations:

$ cat /etc/letsencrypt/cli.ini
preferred-chain = Fake LE Root X2

If you specify an issuer that does not exist, Certbot will complain when running interactively:

Certbot has been configured to prefer certificate chains with issuer 'Fake LE Root xyxy', but no chain from the CA matched this issuer. Using the default certificate chain instead.

4 Likes

Ansible’s acme_certificate also supports it (https://docs.ansible.com/ansible/2.10/collections/community/crypto/acme_certificate_module.html#parameter-select_chain), though I haven’t tested it with the Boulder implementation yet.

2 Likes

@_az, thanks again for helping make this feature work in Certbot! :tada:

2 Likes

I’ve just added support for alternate chains to uacme release 1.5. Check the -l option documented in the manpage

1 Like

I'm working on support for this now too, and have a few questions as the RFC doesn't have many words on the subject:

The server MAY provide one or more link relation header fields
[RFC8288] with relation "alternate". Each such field SHOULD express
an alternative certificate chain starting with the same end-entity
certificate. This can be used to express paths to various trust
anchors. Clients can fetch these alternates and use their own
heuristics to decide which is optimal.

Under pebble with PEBBLE_ALTERNATE_ROOTS=2, I see these headers when downloading a certificate:

print(_certificate_headers["link"])
'<https://0.0.0.0:14000/dir>;rel="index", 
 <https://0.0.0.0:14000/certZ/0963addd1872e8c5/alternate/1>;rel="alternate",
 <https://0.0.0.0:14000/certZ/0963addd1872e8c5/alternate/2>;rel="alternate"
 '

Can people confirm for me:

  1. There is no URL for the certificate itself in this header response, just the alternates
  2. the response on each URL will be a fullchain pem of SignedCert (+ Intermediates)? + CACertificate [as the CACertificate signing the client's certificate is an intermediate of the off-line root, and there could be intermediates in that chain, but realistically there won't be as certbot and other standard clients can only handle a single upchain certificate right now)
  3. there is no link a url of the CACertificate (e.g. https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem.txt)

I have not tested this yet, so I am unclear on the following...

Will the alternate signed certificates be different from one another?

I haven't seen the signing mechanism in boulder and am far from an expert on OpenSSL, so I don't know if I am expecting a single payload signed by multiple keys, or multiple payloads each signed by a different key (both of which are possible in gpg and other cryptography systems).

Thanks in advance!

1 Like

For both Pebble and Boulder , every certificate URL will include alternate links for every available certificate URL, excluding itself.

I think for a client, the most simple thing is: pay attention to the first set of alternate links and do not process them recursively.

What's the difference between Intermediate and CACertificate? I don't think it can ever contain a trust anchor (self-signed CA), if that's what you're asking. But I'm not sure.

If you request the certificate in a single-certificate format like DER (where supported by the server), it would be sent in an up link.

Otherwise, I don't think so.

The end-entity certificate is always the same.

1 Like

Thanks, @_az

The bit of important info I was most concerned with was "excluding itself". I kept thinking I was missing something.

Ah ha! That is why I was getting confused!

I was hoping this was the case... but now I am curious and need to look into how OpenSSL does this!

1 Like

Whoops, missed that one. in part, that's what I was thinking. i was more concerned with scenarios I've seen with commercial vendors where there is a long chain of 3+ certs. I can't recall what that was though.

1 Like

The gogetssl example:

Looks like they chose to cross-sign their root, so "ECC Certification Authority" exists both as a root and as an intermediate.

I guess the equivalent with Let's Encrypt would be if Boulder started sending a fullchain with both versions of "Let's Encrypt Authority X3" in it. Nothing stopping another ACME CA from doing something like that, I suppose.

1 Like

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

Just to clarify: Is the cli.ini entry:

preferred-chain = X
OR
preferred_chain = X

[OR do both work?]