Skip to content
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

Do not destroy SNIs when updating unrelated certificate fields #386

Merged
merged 1 commit into from
May 18, 2021

Conversation

rainest
Copy link
Contributor

@rainest rainest commented May 14, 2021

The first commit here is a noisy chore. Review 6de9ee2 for the meat of this change.

#356 occurs when updating a certificate without modifying its SNIs. We strip SNIs from certificate objects to handle SNIs separately, but the Kong admin API behavior for certificate PUTs handles an empty SNI set on certificates as an instruction to delete those SNIs (probably because SNIs can't exist independent of certificates and because there's a strict one-to-one certificate-to-SNI relationship).

To work around this, this change copies the existing certificate's SNIs out of state during updates and sets them on the updated certificate object before sending it. This preserves the SNI list if it is unchanged while still updating SNIs if they do change (subsequent diffs on the SNIs themselves handle that).

Fix #356

@rainest rainest requested a review from a team as a code owner May 14, 2021 19:42
@rainest
Copy link
Contributor Author

rainest commented May 14, 2021

cert_test.txt shows some example syncs with the changes against testcerts.tar.gz

Note that there was one small change after the test run: originally, I only copied the current SNIs onto the new certificate, so this would spuriously report that it was adding SNIs even if they were unchanged (this was only a cosmetic issue with the diff--the PUT had effect it should). I later amended the commit to copy it onto both, since the current certificate in the update is only used in the diff, and doing so resolves that diff issue.

@codecov-commenter
Copy link

Codecov Report

Merging #386 (6de9ee2) into main (f8e5f95) will decrease coverage by 0.07%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #386      +/-   ##
==========================================
- Coverage   53.59%   53.52%   -0.08%     
==========================================
  Files          62       62              
  Lines        5034     5069      +35     
==========================================
+ Hits         2698     2713      +15     
- Misses       2037     2057      +20     
  Partials      299      299              
Impacted Files Coverage Δ
cmd/root.go 53.69% <0.00%> (-3.33%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f8e5f95...6de9ee2. Read the comment docs.

@rainest rainest mentioned this pull request May 17, 2021
Copy link
Contributor

@shaneutt shaneutt left a comment

Choose a reason for hiding this comment

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

Ultimately my read of this patch based on the description is that this will take care of it, I have no blockers (though please do see my comments below) however, due to the lack of testing for this code path I would appreciate if we could please write a small report about our manual testing of this patch before we merge this.

diff/cert.go Show resolved Hide resolved
diff/cert.go Show resolved Hide resolved
@hbagdi
Copy link
Member

hbagdi commented May 18, 2021

In the spirit of atomic and smaller PRs, please send a different PR for the typo and remove that commit from this PR.

Copy link
Member

@hbagdi hbagdi left a comment

Choose a reason for hiding this comment

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

The special handling of SNIs in Kong continues to be a pain point in decK. Another lesson learned with API design.

@@ -85,6 +85,18 @@ func (sc *Syncer) createUpdateCertificate(

// found, check if update needed
if !currentCertificate.EqualWithOpts(certificateCopy, false, true) {
currentSNIs, err := sc.currentState.SNIs.GetAllByCertID(*currentCertificate.ID)
Copy link
Member

Choose a reason for hiding this comment

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

This is a fairly special case. Do you mind copying the git commit body in here as a code comment to help future maintainers?

@hbagdi
Copy link
Member

hbagdi commented May 18, 2021

Please only merge the relevant patch in this PR. The typo fix should be its own PR.

When decK must update a certificate, retrieve the current certificate's
set of SNIs, convert them to strings, and set these on the updated
certificate.

Certificate and SNI objects have a special relationship. A PUT request
(which we use for updates) with a certificate that contains no SNI
children will in fact delete any existing SNI objects associated with
that certificate, rather than leaving them as-is. Because decK considers
SNIs separate objects and strips SNI child objects from certificate
objects, updates to other certificate fields will PUT a certificate with
no SNIs and inadvertently delete existing SNIs.

Not stripping SNIs from certificate objects in general presents its own
issues, as decK will attempt to operate on both objects and generate
conflicts.

To work around these issues, this change sets SNIs on certificates ONLY
during update requests using the current certificate's SNI list. If
there are changes to the SNIs, subsequent actions on the SNI objects
will handle those.

Fix #356
@rainest rainest merged commit f36cc7a into main May 18, 2021
@rainest rainest deleted the fix/preserve-cert-sni branch May 18, 2021 22:06
AntoineJac pushed a commit that referenced this pull request Jan 23, 2024
When decK must update a certificate, retrieve the current certificate's
set of SNIs, convert them to strings, and set these on the updated
certificate.

Certificate and SNI objects have a special relationship. A PUT request
(which we use for updates) with a certificate that contains no SNI
children will in fact delete any existing SNI objects associated with
that certificate, rather than leaving them as-is. Because decK considers
SNIs separate objects and strips SNI child objects from certificate
objects, updates to other certificate fields will PUT a certificate with
no SNIs and inadvertently delete existing SNIs.

Not stripping SNIs from certificate objects in general presents its own
issues, as decK will attempt to operate on both objects and generate
conflicts.

To work around these issues, this change sets SNIs on certificates ONLY
during update requests using the current certificate's SNI list. If
there are changes to the SNIs, subsequent actions on the SNI objects
will handle those.

Fix #356
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lose snis when updating certificate
4 participants