Draft 13 key rollover compatibility

Continuing the discussion from ACME v2 - Draft 13 compliant key rollover:

I haven't tested this at all yet. But I'm wondering whether I can send both newkey and oldkey in the inner JWS and have it effectively be compatible with both drafts. Has anyone tried it? Does it throw an error today or does Boulder ignore fields it's not expecting (like clients are supposed to do).

If things are going to break, I'm trying to figure out how to time the updated release of my client. Do I just wait until the Production live date and have people testing against staging be broken after the change goes live there? Do I release a beta version with draft-13 support that people can opt into? What do people normally do in situations like this?

1 Like

I've implemented that several months ago (when I saw the discussion about whether to change this) for Ansible's acme_account module, and it worked great for me so far. I guess I'll find out soon (on August 14th) whether this also works with the draft-13 version of Boulder, but I'm optimistic it will. And looking at the implementation, I think my optimism is correct :wink:

1 Like

Nice. Just did a quick test myself against staging where I sent both newKey and oldKey in the inner JWS. It did not throw an error and appears to have completed the rollover successfully. So yay! Perhaps there was nothing to worry about.

If this continues through the draft-13 implementation, it seems like I can release an interim version of my client that includes both. Then once the draft-13 is live everywhere, release another version that removes the legacy field.

Hi @rmbolger

These are good questions and I'm interested in hearing the perspective of client developers. I definitely try to think about these things when planning the server side change.

I wrote the implementation intending that this would work. It looks like I missed testing this concrete case in the unit tests (doh!) I will fix that and update the API announcement. Thanks for asking!

:+1:

1 Like

My tests show this approach should work :+1: - Sign in to GitHub · GitHub

=== RUN   TestKeyRollover
=== RUN   TestKeyRollover/Missing_account_URL
=== RUN   TestKeyRollover/Missing_new_key_from_inner_payload
=== RUN   TestKeyRollover/New_key_is_the_same_as_the_old_key
=== RUN   TestKeyRollover/Inner_JWS_signed_by_the_wrong_key
=== RUN   TestKeyRollover/Valid_key_rollover_request,_key_exists
=== RUN   TestKeyRollover/Valid_key_rollover_request
=== RUN   TestKeyRollover/Valid_key_rollover_request,_added_ACME13KeyRollover_compat
=== RUN   TestKeyRollover/ACME13KeyRollover,_legacy_rollover_request
=== RUN   TestKeyRollover/ACME13KeyRollover,_Missing_account_URL
=== RUN   TestKeyRollover/ACME13KeyRollover,_incorrect_old_key
=== RUN   TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request,_key_exists
=== RUN   TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request
=== RUN   TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request,_legacy_compat
--- PASS: TestKeyRollover (1.25s)
    --- PASS: TestKeyRollover/Missing_account_URL (0.04s)
    --- PASS: TestKeyRollover/Missing_new_key_from_inner_payload (0.04s)
    --- PASS: TestKeyRollover/New_key_is_the_same_as_the_old_key (0.06s)
    --- PASS: TestKeyRollover/Inner_JWS_signed_by_the_wrong_key (0.05s)
    --- PASS: TestKeyRollover/Valid_key_rollover_request,_key_exists (0.05s)
    --- PASS: TestKeyRollover/Valid_key_rollover_request (0.05s)
    --- PASS: TestKeyRollover/Valid_key_rollover_request,_added_ACME13KeyRollover_compat (0.05s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_legacy_rollover_request (0.04s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_Missing_account_URL (0.04s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_incorrect_old_key (0.04s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request,_key_exists (0.05s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request (0.05s)
    --- PASS: TestKeyRollover/ACME13KeyRollover,_Valid_key_rollover_request,_legacy_compat (0.05s)
PASS
ok  	github.com/letsencrypt/boulder/wfe2	(cached)

I updated the API announcement to include this advice. Thanks @rmbolger!

@cpu Thanks for adding that test! :slight_smile:

I definitely try to think about these things when planning the server side change.

Out of curiosity: why not support both ways simultaneously, at least for some time (at least on production, I'd disable the old way pretty quickly on staging)? That would give client developers a bit more time to adjust their clients and get the new versions distributed.

1 Like

I thought about this but there aren't very many clients that have implemented ACME v2 and key rollover. In practice in the production environment we get <30 successful ACME v2 key rollover requests in a month. With that in mind I wanted to move fairly aggressively on this change because there is a burden (both in code, configuration and in brains!) for having to support both.

If there's significant outcry from users and developers we could definitely revisit the timeline. Overall it's a fairly minor change and shouldn't require gnarly code changes.

1 Like

@cpu Ok, that’s very much understandable!

1 Like

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