Repository navigation
Poll the ACME order URL after finalize instead of the Location header - #9430
wallrj-cyberark wants to merge 1 commit into
Conversation
|
Skipping CI for Draft Pull Request. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
wallrj-cyberark
left a comment
There was a problem hiding this comment.
Self-review. Everything under third_party/forked/acme is generated by make update-third-party, so the only hand-written changes are in pkg/, test/integration/ and klone.yaml.
| // Call to CreateCertFromOrder finalizes the ACME order. This call can only be made once. | ||
| // The order URL is passed in because RFC 8555 does not require the finalize | ||
| // response to carry a Location header, and Pebble omits it. | ||
| certSlice, certURL, err := cl.CreateCertFromOrder(ctx, &acmeapi.Order{URI: o.Status.URL, FinalizeURL: o.Status.FinalizeURL}, derBytes, true) |
There was a problem hiding this comment.
CreateCertFromOrder only reads URI and FinalizeURL from the order, so a partial acme.Order built from the Order status is enough. It avoids an extra GetOrder round trip before finalizing. Both fields are always set by this point: the Sync switch returns early while status.url or status.finalizeURL is empty.
|
The follow-up that moves the forked acme package onto upstream's new ACME profiles support is #9431. It is master-only and stacked on this PR, so this one stays small enough to cherry-pick to |
8e8f082 to
63225e7
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The implementation consistently removes reliance on the optional header and includes targeted unit and Pebble coverage.
0 open findings
What changed in this PR
Updates ACME order finalization to poll the persisted order URL instead of relying on an optional Location header.
Changes:
- Vendors
CreateCertFromOrderfrom the crypto fork. - Updates controller and client interfaces to use the order and finalize URLs.
- Adds unit and Pebble coverage for missing finalize
Locationheaders.
The pinned crypto fork PR remains an acknowledged merge prerequisite.
| File | Description |
|---|---|
third_party/klone.yaml |
Updates the crypto fork revision. |
third_party/forked/acme/types.go |
Updates finalization documentation. |
third_party/forked/acme/rfc8555.go |
Adds order-aware certificate creation and polling. |
third_party/forked/acme/rfc8555_test.go |
Tests header-independent finalization. |
third_party/forked/acme/pebble_test.go |
Updates Pebble and exercises the new API. |
third_party/forked/acme/internal/acmeprobe/prober.go |
Migrates probe finalization calls. |
third_party/forked/acme/acme.go |
Updates deprecated API guidance. |
test/integration/acme/orders_controller_test.go |
Updates the integration fake. |
pkg/controller/acmeorders/sync.go |
Passes persisted order and finalize URLs. |
pkg/controller/acmeorders/sync_test.go |
Verifies both URLs are forwarded. |
pkg/acme/client/middleware/logger.go |
Wraps and labels the new operation. |
pkg/acme/client/interfaces.go |
Updates the ACME client contract. |
pkg/acme/client/fake.go |
Updates the test client implementation. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
wallrj
left a comment
There was a problem hiding this comment.
I checked the vendored hunks against golang/crypto b4dcfb54b. They are byte-identical, with autocert dropped as intended. The fake, the logger middleware and the real client are the only implementations of acmecl.Interface in this repo, and all three are updated. The e2e Pebble fork is ahead of v2.9.0, so it does omit the Location header as described.
Two things outside the diff:
- The workaround comment and its
TODO(wallrj)inupdateOrderStatusFromACMEOrderdescribe the bug this PR vendors the fix for:. The vendoredcert-manager/pkg/controller/acmeorders/sync.go
Lines 359 to 366 in 63225e7
GetOrderandWaitOrdernow fillo.URIfrom the request URL, so theif acmeOrder.URI != ""guard is dead for the real client. Please delete the comment and the guard, or reword it to say why the guard stays. - The commit trailer and the last line of the description should name the model:
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>and[Claude Fable 5.1].
The inline comments below are follow-ups rather than blockers.
[Claude Fable 5.1]
- The forked x/crypto/acme CreateOrderCert polls the order at the URL in
the finalize response's Location header. RFC 8555 does not require that
header and Pebble v2.9.0+ omits it, so every finalize against the e2e
Pebble fails with `Post "": unsupported protocol scheme ""` and the
Order is requeued.
- The requeue opens a window in which the Order controller can finalize
the same order a second time. Pebble then answers 403 orderNotReady
because the order is still "processing", and cert-manager marks the
Order as errored. This fails ACME e2e tests intermittently.
- Re-vendor the forked acme package from cert-manager/crypto with
golang/crypto b4dcfb54b ("acme: support standards-compliant order
finalization") cherry-picked. It adds CreateCertFromOrder, which polls
the order's own URI.
- Use CreateCertFromOrder in the Order controller, passing the URL and
finalize URL already stored in the Order status.
Upstream issue: golang/go#77704
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Richard Wall <richard.wall@cyberark.com>
63225e7 to
d1a17a4
Compare
|
Replies to the two points in the review body:
[with Claude] |
Pull Request Motivation
ACME e2e tests fail intermittently on master with:
For example,
ci-cert-manager-master-e2e-v1-35on 2026-10-05.The cause is in our forked
x/crypto/acme. After finalizing,CreateOrderCertpolls the order at the URL in the finalize response'sLocationheader. RFC 8555 does not require that header, and Pebble v2.9.0+ omits it. So every finalize in e2e fails withPost "": unsupported protocol scheme "", and the Order is requeued. Even a passing run logs this:ci-cert-manager-master-e2e-v1-37today has 206 of these lines in the controller log.Usually the retry sees the order as
validand recovers. Sometimes the controller finalizes the same order a second time while Pebble is still issuing. Pebble answers 403 because the order isprocessing, andfinalizeOrderonly recovers from a 403 when the order isvalid, so it marks the Order as errored.golang/crypto fixed this in b4dcfb54b (golang/go#77704) by adding
CreateCertFromOrder, which polls the order's own URI. This PR:master.CreateCertFromOrder, passing the URL already stored in the Order status.#8968 handles the
processing403 infinalizeOrderfor a different trigger, where Let's Encrypt shares one order between two Order resources (#8960). It is still needed after this PR: if the controller restarts while it waits for a finalized order, the next sync finalizes again and gets the same 403. This PR makes the double finalize rarer, but does not remove it.I would like to cherry-pick this to
release-1.21once merged, because the 1.21 e2e runs the same Pebble.How this was tested
make verify-golangci-lint: 0 issues.go test ./pkg/controller/acmeorders/... ./pkg/acme/... ./third_party/forked/acme/...passes. The forked package'sTestWithPebblenow runs against Pebble v2.10.1, which omits the header.sync_test.gonow checks that the controller passesstatus.urlandstatus.finalizeURL. With the URI dropped from the call, it fails withInvalid order: expected URI "http://testurl.com/abcde" ... got "".TestWithPebbleagainst Pebble v2.10.1 fails onmasterwithPost "": unsupported protocol scheme ""and passes with the cherry-pick.unsupported protocol schemelines. I will check this PR's e2e artifacts for that.Why the vendored files change
The files under
third_party/forked/acmewere produced bymake update-third-partyafter bumpingrepo_hashinthird_party/klone.yaml. They match golang/crypto b4dcfb54b except forautocert, which we do not vendor. The metrics label stayscreate_order_cert, so existing dashboards keep working.Kind
/kind bug
/kind flake
Release Note
[with Claude]