Skip to content

fix(bucket): clean up orphaned cert-manager ACME solver resources on delete (#3060) - #3076

Merged
Aleksei Sviridkin (lexfrei) merged 3 commits into
mainfrom
fix/bucket-acme-solver-orphaned
Jun 30, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 3 commits into
mainfrom
fix/bucket-acme-solver-orphaned

Conversation

@scooby87

@scooby87 scooby87 commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

After deleting a Bucket app CR, cert-manager's temporary ACME HTTP-01 solver
resources (cm-acme-http-solver-* Ingress/Pod/Service) were left orphaned in the
tenant namespace. They are created by cert-manager to answer an ACME challenge
and are owned by the Challenge/Order → Certificate, not by the app Ingress.
If a challenge gets stuck and the app is deleted, the parent Ingress is removed
but the orphaned challenge leaves the solver objects with no live owner to
cascade-delete them, so Helm/Flux uninstall cannot reap them.

This adds a post-delete cleanup hook that deletes the release's
Certificate/Order/Challenge (cert-manager then cascade-removes the solver
objects) and then sweeps any leftover solver objects by the reliable
acme.cert-manager.io/http01-solver=true label.

RBAC is verified against the vendored cert-manager CRDs
(cert-manager.io → certificates; acme.cert-manager.io → orders, challenges)
plus core services/pods and networking.k8s.io ingresses. The cleanup Job is
hardened: non-root (uid 65534), read-only root fs, all caps dropped,
seccompProfile: RuntimeDefault. Failures are logged but never block teardown.

The preventive wildcard-cert guard the issue mentions already exists in the
vendored bucket-system Ingress template (it drops the ACME annotations in
wildcard mode), so no preventive change is needed — only cleanup.

No user data is affected: only cert-manager's transient challenge artifacts are
removed.

Fixes #3060.

Release note

fix(bucket): clean up orphaned cert-manager ACME http01-solver resources (Ingress/Pod/Service) left behind after a Bucket app is deleted.

Summary by CodeRabbit

  • New Features
    • Added a bucket app test command that runs Helm unit tests.
    • Introduced a post-delete ACME cleanup hook to remove release-scoped cert-manager TLS and HTTP-01 solver resources, using dedicated least-privilege access controls.
  • Bug Fixes
    • Improved cleanup safety with bounded execution and hardened container security.
  • Tests
    • Added a Helm test suite covering rendered hook documents, including host-scoped targeting and negative assertions to prevent overly broad deletions.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where cert-manager ACME solver resources remain in the cluster after a Bucket application is deleted. By implementing a post-delete cleanup hook, the system now ensures that all associated certificates, orders, challenges, and any leftover solver Ingresses, Services, or Pods are properly reaped, preventing resource leakage in the tenant namespace.

Highlights

  • Orphaned Resource Cleanup: Introduced a post-delete Helm hook to automatically remove cert-manager ACME challenge resources and orphaned HTTP-01 solver objects when a Bucket app is uninstalled.
  • Security Hardening: The cleanup Job is configured with non-root execution, a read-only root filesystem, dropped capabilities, and a restricted seccomp profile.
  • Testing: Added comprehensive helm-unittest coverage to verify the cleanup Job, ServiceAccount, and RBAC permissions.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@github-actions github-actions Bot added area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files labels Jun 25, 2026
@coderabbitai

coderabbitai Bot commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 61f6aede-5909-4900-99b7-1bb75702bfed

📥 Commits

Reviewing files that changed from the base of the PR and between 58b2a3d and 6a43adb.

📒 Files selected for processing (2)
  • packages/apps/bucket/templates/hooks/cleanup-acme.yaml
  • packages/apps/bucket/tests/cleanup_acme_test.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/apps/bucket/tests/cleanup_acme_test.yaml

📝 Walkthrough

Walkthrough

Adds a post-delete Helm hook for Bucket that deletes cert-manager ACME cleanup resources, plus a dedicated service account, RBAC, and Helm unittest coverage. Also adds a make test target to run the chart tests.

Changes

Post-delete ACME cleanup

Layer / File(s) Summary
Test target and hook rendering
packages/apps/bucket/Makefile, packages/apps/bucket/templates/hooks/cleanup-acme.yaml, packages/apps/bucket/tests/cleanup_acme_test.yaml
Adds a helm unittest target and tests for the rendered cleanup hook, including job metadata, command behavior, resource sizing, service account usage, and role assertions.
Cleanup job and command
packages/apps/bucket/templates/hooks/cleanup-acme.yaml
Renders a hardened post-delete Job whose script deletes release-scoped cert-manager resources and host-scoped HTTP-01 challenge and ingress leftovers.
Cleanup service account and RBAC
packages/apps/bucket/templates/hooks/cleanup-acme.yaml
Adds the cleanup ServiceAccount, a restricted Role, and a RoleBinding for the post-delete hook.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #3061: The new post-delete ACME cleanup hook, host-scoped solver cleanup, and Helm unittest coverage align with the reported orphaned cert-manager HTTP-01 resource cleanup objective.

Suggested labels

area/kubernetes, area/networking

Suggested reviewers

  • kvaps
  • lllamnyp
  • androndo
  • IvanHunters
  • sircthulhu
  • myasnikovdaniil
  • lexfrei

Poem

🐰 I hopped through hooks and tidied the burrow bright,
kubectl nibbled leftovers out of sight.
Certificates and solver bits, gone with a bound,
Now Bucket’s cleanup hops gently to ground.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title succinctly describes the bucket delete cleanup for orphaned cert-manager ACME solver resources.
Linked Issues check ✅ Passed The cleanup hook targets the reported leak by removing the release certificate and matching challenges, then cleaning solver ingress resources.
Out of Scope Changes check ✅ Passed The Makefile test target and Helm test suite directly support the new cleanup hook; no unrelated changes stand out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/bucket-acme-solver-orphaned

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a post-delete Helm hook to clean up orphaned cert-manager ACME resources for the bucket application, along with corresponding unit tests and a Makefile test target. The reviewer feedback highlights a critical issue where a blanket sweep of all http01-solver resources in the namespace could disrupt active ACME challenges for other applications sharing the same namespace. To address this, the reviewer suggests removing the unsafe sweep, narrowing the RBAC permissions to adhere to the principle of least privilege, and updating the unit tests accordingly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +47 to +58
kubectl delete certificate {{ .Release.Name }}-ui-tls -n {{ .Release.Namespace }} --ignore-not-found \
|| echo "WARNING: cert-manager cleanup failed for {{ .Release.Name }}; orphaned ACME resources may remain" >&2
kubectl delete certificate,order,challenge -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} --ignore-not-found \
|| echo "WARNING: cert-manager cleanup failed for {{ .Release.Name }}; orphaned ACME resources may remain" >&2
# Backstop sweep: if the challenge never completed there may be no
# live owner to cascade the deletion, so remove any leftover
# http01 solver Ingress/Service/Pod directly. This label is set by
# cert-manager on every solver object and is the reliable selector.
echo "Sweeping leftover ACME http01-solver objects..."
kubectl delete ingress,svc,pod -n {{ .Release.Namespace }} -l acme.cert-manager.io/http01-solver=true --ignore-not-found \
|| echo "WARNING: ACME solver sweep failed for {{ .Release.Name }}; orphaned solver objects may remain" >&2
echo "ACME cleanup complete."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Sweeping all resources with the label acme.cert-manager.io/http01-solver=true in the namespace is highly dangerous. In Cozystack, multiple apps can share the same tenant namespace. Running a blanket delete on all solver resources will disrupt and fail active ACME challenges for other apps in the same namespace. Deleting the Certificate, Order, and Challenge resources is sufficient, as cert-manager will automatically cascade-delete their associated solver resources safely.

              kubectl delete certificate {{ .Release.Name }}-ui-tls -n {{ .Release.Namespace }} --ignore-not-found \
                || echo "WARNING: cert-manager cleanup failed for {{ .Release.Name }}; orphaned ACME resources may remain" >&2
              kubectl delete certificate,order,challenge -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} --ignore-not-found \
                || echo "WARNING: cert-manager cleanup failed for {{ .Release.Name }}; orphaned ACME resources may remain" >&2
              echo "ACME cleanup complete."

Comment on lines +87 to +99
rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "list", "delete"]
- apiGroups: ["acme.cert-manager.io"]
resources: ["orders", "challenges"]
verbs: ["get", "list", "delete"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "delete"]
- apiGroups: [""]
resources: ["services", "pods"]
verbs: ["get", "list", "delete"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Since the blanket sweep of ingresses, services, and pods is removed, we no longer need to grant delete (or any other) permissions on these core resources. Removing these rules adheres to the principle of least privilege and hardens the cleanup Job's RBAC footprint.

rules:
  - apiGroups: ["cert-manager.io"]
    resources: ["certificates"]
    verbs: ["get", "list", "delete"]
  - apiGroups: ["acme.cert-manager.io"]
    resources: ["orders", "challenges"]
    verbs: ["get", "list", "delete"]

Comment on lines +32 to +43
- it: deletes cert-manager resources and sweeps http01-solver leftovers
documentIndex: 0
asserts:
- matchRegex:
path: spec.template.spec.containers[0].command[2]
pattern: "kubectl delete certificate my-bucket-ui-tls -n tenant-root"
- matchRegex:
path: spec.template.spec.containers[0].command[2]
pattern: "kubectl delete certificate,order,challenge -n tenant-root -l app.kubernetes.io/instance=my-bucket"
- matchRegex:
path: spec.template.spec.containers[0].command[2]
pattern: "kubectl delete ingress,svc,pod -n tenant-root -l acme.cert-manager.io/http01-solver=true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Update the test assertions to match the removal of the unsafe backstop sweep command.

  - it: deletes cert-manager resources
    documentIndex: 0
    asserts:
      - matchRegex:
          path: spec.template.spec.containers[0].command[2]
          pattern: "kubectl delete certificate my-bucket-ui-tls -n tenant-root"
      - matchRegex:
          path: spec.template.spec.containers[0].command[2]
          pattern: "kubectl delete certificate,order,challenge -n tenant-root -l app.kubernetes.io/instance=my-bucket"

Comment on lines +55 to +85
- it: grants RBAC on cert-manager, acme and networking/core resources
documentIndex: 2
asserts:
- equal:
path: kind
value: Role
- contains:
path: rules
content:
apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "list", "delete"]
- contains:
path: rules
content:
apiGroups: ["acme.cert-manager.io"]
resources: ["orders", "challenges"]
verbs: ["get", "list", "delete"]
- contains:
path: rules
content:
apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "delete"]
- contains:
path: rules
content:
apiGroups: [""]
resources: ["services", "pods"]
verbs: ["get", "list", "delete"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Update the RBAC test assertions to match the simplified Role permissions.

  - it: grants RBAC on cert-manager and acme resources
    documentIndex: 2
    asserts:
      - equal:
          path: kind
          value: Role
      - contains:
          path: rules
          content:
            apiGroups: ["cert-manager.io"]
            resources: ["certificates"]
            verbs: ["get", "list", "delete"]
      - contains:
          path: rules
          content:
            apiGroups: ["acme.cert-manager.io"]
            resources: ["orders", "challenges"]
            verbs: ["get", "list", "delete"]

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/apps/bucket/templates/hooks/cleanup-acme.yaml`:
- Around line 47-50: The cleanup command in cleanup-acme.yaml is using the Helm
release label selector in kubectl delete, which won’t match cert-manager Order
and Challenge resources. Update the kubectl delete target in the cert-manager
cleanup block to select those resources by the certificate name using the
cert-manager.io/certificate label, keeping the existing delete of the
certificate itself in place. Refer to the cleanup shell block around the kubectl
delete certificate,order,challenge command and preserve the warning behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8586a518-5e87-4600-ac76-90de1e0b5e8a

📥 Commits

Reviewing files that changed from the base of the PR and between 63f9926 and 06d6106.

📒 Files selected for processing (3)
  • packages/apps/bucket/Makefile
  • packages/apps/bucket/templates/hooks/cleanup-acme.yaml
  • packages/apps/bucket/tests/cleanup_acme_test.yaml

Comment thread packages/apps/bucket/templates/hooks/cleanup-acme.yaml Outdated
@scooby87
scooby87 force-pushed the fix/bucket-acme-solver-orphaned branch from 06d6106 to 5dbb352 Compare June 25, 2026 15:48

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — adds a post-delete Job that removes the release-scoped cert-manager Certificate, letting cert-manager cascade-delete the orphaned ACME Order/Challenge/solver objects; deliberately avoids a namespace-wide solver sweep that would kill sibling apps' in-flight challenges.

Business context: deleting a bucket left orphaned cert-manager ACME solver resources behind (#3060).

Verified: the targeted Certificate name is correct — packages/system/bucket/templates/ingress.yaml sets tls.secretName=<bucketName>-ui-tls and bucketName == .Release.Name, so cert-manager's ingress-shim creates Certificate/<release>-ui-tls; deleting it cascades to CertificateRequest -> Order -> Challenge -> solver via ownerReferences. RBAC is scoped to cert-manager/acme resources only, hook ordering (SA -> Role/RoleBinding -> Job) is correct, and the no-blanket-sweep decision is sound and well-commented.

Non-blocking follow-up

  1. The secondary kubectl delete certificate,order,challenge -l app.kubernetes.io/instance=<release> is effectively a no-op: cert-manager doesn't put app.kubernetes.io/instance on Certificate/Order/Challenge (Orders/Challenges carry cert-manager.io/certificate-name). Cleanup still works via the name-based Certificate delete + cascade, so it's harmless — but either switch the selector to cert-manager.io/certificate-name=<release>-ui-tls or drop the redundant line so it doesn't imply coverage it doesn't provide.

…delete (#3060)

cert-manager ACME http01-solver Ingress/Pod/Service objects were left
orphaned after a Bucket app CR was deleted (a stuck challenge leaves them
without a live owner to cascade-delete). Add a post-delete hook that deletes
the release Certificate/Order/Challenge and sweeps leftover solver objects by
the acme.cert-manager.io/http01-solver label. RBAC verified against the
vendored cert-manager CRDs. The cleanup Job runs non-root with a read-only
root fs and dropped capabilities; failures are logged but never block teardown.

Signed-off-by: Алексей Артамонов <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/apps/bucket/tests/cleanup_acme_test.yaml (2)

13-147: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin the total rendered document count.

These tests only verify documents 0..3. If templates/hooks/cleanup-acme.yaml starts emitting a fifth manifest, the suite still passes and an extra hook/RBAC object can slip in unnoticed. Add a hasDocuments: { count: 4 } guard for the whole template.

Suggested addition
 tests:
+  - it: renders only the expected cleanup hook objects
+    asserts:
+      - hasDocuments:
+          count: 4
+
   - it: renders a post-delete cleanup Job with the expected name and SA
     documentIndex: 0
     asserts:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/apps/bucket/tests/cleanup_acme_test.yaml` around lines 13 - 147, The
cleanup-acme test suite only checks documents 0 through 3, so extra rendered
manifests could be added without failing. Update the cleanup-acme YAML test to
assert the total rendered document count with a hasDocuments count of 4, so
templates like cleanup-acme.yaml cannot emit an unexpected additional hook or
RBAC object. Use the existing cleanup_acme_test.yaml document assertions as the
anchor for where to add the count guard.

14-85: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Assert the hardening contract too.

The PR explicitly relies on this hook running with non-root, read-only, dropped-capability, and RuntimeDefault seccomp settings, but the suite never checks them. A future template change could remove those protections while all of these tests still pass.

Suggested additions
   - it: renders a post-delete cleanup Job with the expected name and SA
     documentIndex: 0
     asserts:
       - equal:
           path: kind
           value: Job
@@
       - equal:
           path: spec.template.spec.restartPolicy
           value: Never
+      - equal:
+          path: spec.template.spec.securityContext.runAsNonRoot
+          value: true
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
+          value: true
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.capabilities.drop[0]
+          value: ALL
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.seccompProfile.type
+          value: RuntimeDefault
       - equal:
           path: spec.template.metadata.labels["policy.cozystack.io/allow-to-apiserver"]
           value: "true"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/apps/bucket/tests/cleanup_acme_test.yaml` around lines 14 - 85, The
cleanup Job test coverage is missing the security hardening assertions, so add
checks in the bucket cleanup Helm test to verify the Job pod template preserves
the non-root, read-only, dropped-capability, and RuntimeDefault seccomp
settings. Update the existing cleanup Job assertions around spec.template.spec
and the container securityContext in cleanup_acme_test.yaml so future changes to
the cleanup template still enforce these protections.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/apps/bucket/templates/hooks/cleanup-acme.yaml`:
- Around line 12-88: The cleanup Job in cleanup-acme.yaml needs runtime bounds
and safer kubectl behavior because the current delete/list flow can hang on
finalizers and hide list failures. Update the Job spec to enforce an execution
timeout with activeDeadlineSeconds, and adjust the kubectl calls in the cleanup
command so deletions use --wait=false and all kubectl get lookups set a request
timeout instead of relying on default waits. Also remove the /dev/null
redirection from the Challenge and Ingress list commands so failures are
surfaced in the job logs, using the existing cleanup command block and kubectl
delete/get loops as the places to change.

---

Nitpick comments:
In `@packages/apps/bucket/tests/cleanup_acme_test.yaml`:
- Around line 13-147: The cleanup-acme test suite only checks documents 0
through 3, so extra rendered manifests could be added without failing. Update
the cleanup-acme YAML test to assert the total rendered document count with a
hasDocuments count of 4, so templates like cleanup-acme.yaml cannot emit an
unexpected additional hook or RBAC object. Use the existing
cleanup_acme_test.yaml document assertions as the anchor for where to add the
count guard.
- Around line 14-85: The cleanup Job test coverage is missing the security
hardening assertions, so add checks in the bucket cleanup Helm test to verify
the Job pod template preserves the non-root, read-only, dropped-capability, and
RuntimeDefault seccomp settings. Update the existing cleanup Job assertions
around spec.template.spec and the container securityContext in
cleanup_acme_test.yaml so future changes to the cleanup template still enforce
these protections.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 481bd958-3015-401d-b917-3b21df58310e

📥 Commits

Reviewing files that changed from the base of the PR and between 06d6106 and 4425d3a.

📒 Files selected for processing (3)
  • packages/apps/bucket/Makefile
  • packages/apps/bucket/templates/hooks/cleanup-acme.yaml
  • packages/apps/bucket/tests/cleanup_acme_test.yaml
✅ Files skipped from review due to trivial changes (1)
  • packages/apps/bucket/Makefile

Comment thread packages/apps/bucket/templates/hooks/cleanup-acme.yaml
…ctor

Address review feedback on the post-delete cleanup hook:

- Target Orders/Challenges by cert-manager's own
  cert-manager.io/certificate-name=<release>-ui-tls label instead of the
  Helm app.kubernetes.io/instance label, which cert-manager never sets on
  those resources (the old selector was a silent no-op).
- Bound the Job with activeDeadlineSeconds=120 and backoffLimit=0 so a
  stuck finalizer or hung API call cannot block the uninstall.
- Add --wait=false --request-timeout=30s to every kubectl delete/get so
  the hook never hangs on slow or finalizer-blocked deletes.
- Surface list failures in the job log instead of redirecting to
  /dev/null.
- Tests: assert the bounded execution and security-hardening contract,
  pin the rendered document count to 4, and update selector assertions.

Assisted-By: Claude <[email protected]>
Signed-off-by: Алексей Артамонов <[email protected]>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT LGTM — the orphaned-solver cleanup itself is correct and safe, but one line is a no-op carried by an inaccurate comment and pinned by a test, which should be cleaned up before merge.

The fix resolves the orphaned cert-manager ACME solver objects through three mechanisms I verified: the name-based kubectl delete certificate <release>-ui-tls plus owner cascade; a host-scoped Challenge sweep filtered on .spec.dnsName; and a host-scoped solver-Ingress sweep filtered on .spec.rules[0].host. The host value matches the Challenge dnsName and the solver Ingress rule host, and there is no namespace-wide blanket delete over the shared acme.cert-manager.io/http01-solver label — the label-wide get is filtered by host and only matching objects are deleted by name, so sibling apps are untouched. The bounded execution (activeDeadlineSeconds, backoffLimit: 0, --request-timeout=30s --wait=false), RBAC scope, and hardening are all correct, and the negative no-blanket-sweep test assertions are the right call.

Blocker (small, but it's a false-coverage + inaccurate-comment issue):

  • templates/hooks/cleanup-acme.yaml:72 — kubectl delete order,challenge -n <ns> -l cert-manager.io/certificate-name=<release>-ui-tls is a no-op. Challenge objects carry no labels at all, and on an Order the cert-manager.io/certificate-name value is an annotation (copied from the CertificateRequest), not a label — so a label selector matches neither. The accompanying comment (:69-70, "cert-manager stamps them with its own cert-manager.io/certificate-name label") is therefore factually wrong, and tests/cleanup_acme_test.yaml:74 pins this no-op as if it were meaningful coverage. Orders are already reaped by the Certificate cascade and Challenges by the working dnsName sweep, so please drop this line along with its test assertion and the inaccurate comment, rather than keeping a selector that deletes nothing and a comment that misstates how cert-manager labels these objects.

Per maintainer review: the label selector
cert-manager.io/certificate-name=<release>-ui-tls matches nothing —
Challenge objects carry no labels, and on Orders certificate-name is an
annotation (not a label). Orders are already reaped by the Certificate
owner cascade and Challenges by the host-scoped .spec.dnsName sweep, so
the line deleted nothing and its comment misstated cert-manager labeling.

Remove the dead delete, replace the inaccurate comment, and drop the
test assertion that pinned it; add negative assertions so a label-based
order/challenge delete cannot be reintroduced.

Assisted-By: Claude <[email protected]>
Signed-off-by: Алексей Артамонов <[email protected]>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — the previously-raised blocker is resolved; the orphaned-solver cleanup is correct and release-scoped.

The no-op label-based order/challenge delete (-l cert-manager.io/certificate-name=<release>-ui-tls, which matched nothing — Challenges are unlabeled and that value is an annotation on Orders, not a label) has been dropped, together with its inaccurate comment and the test assertion that pinned it. The replacement comment accurately explains why there is no label selector for Order/Challenge.

Re-verified against packages/system/bucket/templates/ingress.yaml:

  • Certificate name <release>-ui-tls matches the ingress-shim secretName.
  • HOST <release>.<_namespace.host> matches both the Challenge .spec.dnsName and the solver Ingress .spec.rules[0].host, by exact equality (not a prefix), so a sibling like <release>-2.<host> is never affected.
  • The if not $wildcardSecret guard already suppresses per-host ACME, so wildcard mode has nothing to clean.
  • RBAC stays least-privilege (no services/pods — solver Service/Pod cascade with their Challenge), execution is bounded (activeDeadlineSeconds 120, backoffLimit 0, per-call --request-timeout/--wait=false), and the script always exits 0 so a failure never blocks uninstall.

Tests cover the contract, including the negative assertions (no namespace-wide solver sweep, no services/pods RBAC).

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit 81198b2 into main Jun 30, 2026
15 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the fix/bucket-acme-solver-orphaned branch June 30, 2026 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bucket: cert-manager ACME http-solver resources orphaned after deletion

2 participants