Skip to content

Certificates: preventing CertificateRequest creation runaway #5567

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

JoshVanL
Copy link
Contributor

@JoshVanL JoshVanL commented Nov 9, 2022

Fixes #4846

PR adds a new Condition type to Certificates DuplicateSecretName. This condition is managed by a new DuplicateSecretName controller, and sets this condition on Certificates which have the same spec.secretName as that as another Certificate in the same Namespace. This condition blocks issuance.

/kind feature
/milestone v1.11

Certificates: Adds a new DuplicateSecretName condition on Certificate resources which will be set when the Certificate has a `spec.secretName` value of that of another Certificate in the same Namespace. This condition will block issuance of that Certificate. The condition will be removed once the duplication of secretName has been fixed, and normal issuance can continue. This condition is used to both prevent CertificateRequest runaway, as well as make it clear what the problem is to users.

You can check that this PR works by installing the below manifests, and view it is currently broken on master but fixed with this PR.

$ cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: ca
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: foo
spec:
  commonName: test
  secretName: hello
  privateKey:
    algorithm: RSA
    rotationPolicy: Always
  issuerRef:
    name: ca
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: bar
spec:
  commonName: test2
  secretName: hello
  issuerRef:
    name: ca
  privateKey:
    algorithm: ECDSA
    rotationPolicy: Always
EOF
$ kubectl get cr --watch

@jetstack-bot jetstack-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/feature Categorizes issue or PR as related to a new feature. labels Nov 9, 2022
@jetstack-bot jetstack-bot added this to the v1.11 milestone Nov 9, 2022
@jetstack-bot jetstack-bot added dco-signoff: yes Indicates that all commits in the pull request have the valid DCO sign-off message. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. area/api Indicates a PR directly modifies the 'pkg/apis' directory area/testing Issues relating to testing approved Indicates a PR has been approved by an approver from all required OWNERS files. area/deploy Indicates a PR modifies deployment configuration labels Nov 9, 2022
@JoshVanL
Copy link
Contributor Author

JoshVanL commented Nov 9, 2022

Implementation is still not quite right.. we shouldn't fail on a duplicate secret name, and instead just block on the issuance. Triggering a new issuance on a non-failed Certificate which no longer has a duplicate secret name should happen right away, so the e2e tests are correctly failing.

@JoshVanL JoshVanL changed the title Certificates: preventing CertificateRequest creation runaway WIP: Certificates: preventing CertificateRequest creation runaway Nov 9, 2022
@jetstack-bot jetstack-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 9, 2022
// If Certificate doesn't have Issuing=true condition then we should check
// to ensure all non-issuing related SecretData is correct on the
// Certificate's secret.
return c.ensureSecretData(ctx, log, crt)
}

// If the Certificate has a duplicate Secret name condition set, we should
// fail the issuance. If we discover that we have a duplicate Secret name set
// ourselves, we exit early and wait for that condition to be set.
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need a negation?

@SgtCoDFish
Copy link
Member

This won't make 1.11. I was asked to take a look at this but haven't had a chance. Pushing to 1.12!

@SgtCoDFish SgtCoDFish modified the milestones: v1.11, v1.12 Jan 4, 2023
@jetstack-bot jetstack-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 27, 2023
@vinzent
Copy link
Contributor

vinzent commented Mar 29, 2023

Looking forward to this feature. We already faced the "certificate secret race" multiple times. Issued about 40'000 certificates from our on-premise ACME server.

@maelvls
Copy link
Member

maelvls commented Apr 14, 2023

Hi @JoshVanL! Just to let you know, we will have a code freeze for 1.12 starting Wed 19 April 2023. The code freeze will be waived after the release of 1.12 on Wed 26 April 2023.

@inteon inteon self-assigned this Apr 28, 2023
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from 3cfd601 to d00373a Compare April 28, 2023 08:01
@jetstack-bot jetstack-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 28, 2023
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from 9465bb8 to ca0e839 Compare May 3, 2023 06:58
@inteon
Copy link
Member

inteon commented May 3, 2023

/retest

@inteon inteon changed the title WIP: Certificates: preventing CertificateRequest creation runaway Certificates: preventing CertificateRequest creation runaway May 3, 2023
@jetstack-bot jetstack-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 3, 2023
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from dc4a643 to 6e5f587 Compare May 3, 2023 14:48
@jetstack-bot jetstack-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 9, 2023
@jetstack-bot jetstack-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 3, 2023
@jetstack-bot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from inteon. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@jetstack-bot jetstack-bot removed the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 3, 2023
@drewwells
Copy link

Why does this need a controller? We can check if secret's ownerReference matches the certificates resource ID

@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch 2 times, most recently from eecf685 to 4fc6a8f Compare October 3, 2023 18:59
@inteon
Copy link
Member

inteon commented Oct 3, 2023

@drewwells

Why does this need a controller? We can check if secret's ownerReference matches the certificates resource ID

ownerReferences can be disabled (and probably should be in a production environment): https://cert-manager.io/docs/installation/upgrading/#reinstalling-cert-manager

inteon added 5 commits October 3, 2023 21:54
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch 2 times, most recently from dc7371f to 8320cc7 Compare October 4, 2023 07:54
…ecretName conflict

Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from 8320cc7 to b90e20b Compare October 4, 2023 07:56
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
@inteon
Copy link
Member

inteon commented Oct 4, 2023

I updated the PR:

  • The DuplicateSecretName condition is renamed ot InConflict.
  • Now the Ready condition is set to False when there is an InConflict condition.

The new behavior looks as follows:

$ kubectl -n test get cert | grep True | wc -l
0
$ kubectl -n test get cert -o yaml | grep "secretName: ca-key-pair$" | wc -l
31
$ _bin/cmctl/cmctl-linux-amd64 renew -n test a9
Manually triggered issuance of Certificate test/a9
$ kubectl -n test get cert a9 -o yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  creationTimestamp: "2023-10-04T08:51:11Z"
  generation: 1
  name: a9
  namespace: test
  resourceVersion: "3469"
  uid: f7c8d2ff-d3c6-4489-b183-2d8329a494fc
spec:
  commonName: test
  issuerRef:
    name: ca
  privateKey:
    algorithm: RSA
    rotationPolicy: Always
  secretName: ca-key-pair
status:
  conditions:
  - lastTransitionTime: "2023-10-04T08:51:11Z"
    message: 'Certificate shares the same Secret name as the following Certificates
      in this Namespace: [ a1, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a2,
      a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a3, a30, a31, a4, a5, a6,
      a7, a8 ]. Issuance will block until this is resolved to prevent CertificateRequest
      creation runaway.'
    observedGeneration: 1
    reason: a1,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a2,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a3,a30,a31,a4,a5,a6,a7,a8
    status: "True"
    type: InConflict
  - lastTransitionTime: "2023-10-04T08:51:11Z"
    message: Not ready because Certificate has a "InConflict" condition
    observedGeneration: 1
    reason: InConflict
    status: "False"
    type: Ready
  - lastTransitionTime: "2023-10-04T08:51:57Z"
    message: The certificate has been successfully issued
    observedGeneration: 1
    reason: Issued
    status: "False"
    type: Issuing
  notAfter: "2024-01-02T08:51:57Z"
  notBefore: "2023-10-04T08:51:57Z"
  renewalTime: "2023-12-03T08:51:57Z"
  revision: 1
$ kubectl -n test get cert a8 -oyaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  creationTimestamp: "2023-10-04T08:51:10Z"
  generation: 1
  name: a8
  namespace: test
  resourceVersion: "3436"
  uid: 6add6307-d79d-4e8e-a9e8-15cbfb275a4b
spec:
  commonName: test
  issuerRef:
    name: ca
  privateKey:
    algorithm: RSA
    rotationPolicy: Always
  secretName: ca-key-pair
status:
  conditions:
  - lastTransitionTime: "2023-10-04T08:51:10Z"
    message: 'Certificate shares the same Secret name as the following Certificates
      in this Namespace: [ a1, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a2,
      a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a3, a30, a31, a4, a5, a6,
      a7, a9 ]. Issuance will block until this is resolved to prevent CertificateRequest
      creation runaway.'
    observedGeneration: 1
    reason: a1,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a2,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a3,a30,a31,a4,a5,a6,a7,a9
    status: "True"
    type: InConflict
  - lastTransitionTime: "2023-10-04T08:51:10Z"
    message: Not ready because Certificate has a "InConflict" condition
    observedGeneration: 1
    reason: InConflict
    status: "False"
    type: Ready
  notAfter: "2024-01-02T08:51:57Z"
  notBefore: "2023-10-04T08:51:57Z"
  renewalTime: "2023-12-03T08:51:57Z"
This is the script I used to generate the certs
#!/bin/bash

kubectl create ns test

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
    name: ca
    namespace: test
spec:
    selfSigned: {}
EOF

for i in {1..31}; do

cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
    name: a$i
    namespace: test
spec:
    commonName: test$i
    secretName: ca-key-pair
    privateKey:
        algorithm: RSA
        rotationPolicy: Always
    issuerRef:
        name: ca
EOF

done

@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from fc85050 to 28e298b Compare October 4, 2023 08:55
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
condition := buildInConflictCondition(duplicates)
crt = crt.DeepCopy()
if condition != nil {
apiutil.SetCertificateCondition(crt, crt.Generation, condition.Type, condition.Status, condition.Reason, condition.Message)
Copy link
Member

@maelvls maelvls Oct 6, 2023

Choose a reason for hiding this comment

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

Note: In api-conventions.md, the reason field is described as "a one-word CamelCase reason for the condition's last transition"

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, currently, the reason is used to store what certs are in conflict & this value is actually used by the controller.
As discussed in today's standup, we probably can implement a solution that does not require this.

Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from 2316af9 to 132a779 Compare October 9, 2023 08:04
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
@inteon inteon force-pushed the controllers-certificates-duplicate-secret-name branch from f726d2c to c5155a1 Compare October 9, 2023 11:49
@inteon
Copy link
Member

inteon commented Oct 9, 2023

NOTE: the current implementation makes all conflicting certificates not ready.
A future improvement might be to have 1 certificate (the first created) that continues to work correctly, and only fail the others.

everything breaks (current master)
all conflicting certificates break (this PR)
only the additional certificates break (future PR)

@inteon
Copy link
Member

inteon commented Oct 18, 2023

fixed in #6406

@inteon inteon closed this Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api Indicates a PR directly modifies the 'pkg/apis' directory area/deploy Indicates a PR modifies deployment configuration area/testing Issues relating to testing dco-signoff: yes Indicates that all commits in the pull request have the valid DCO sign-off message. kind/feature Categorizes issue or PR as related to a new feature. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More than one Certificate nominating same Secret induces runaway creation of many CertificateRequests and Orders
9 participants