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

Use GetClientCertificate to allow client cert to be reloaded #537

Merged
merged 9 commits into from
Jul 24, 2024

Conversation

rubenvp8510
Copy link
Contributor

@rubenvp8510 rubenvp8510 commented Jul 2, 2024

What this PR does:
Use GetClientCertificate to reload the client certificates from the disk, similar to what has been done with GetCertificate in this library https://github.com/prometheus/exporter-toolkit/blob/master/web/tls_config.go#L204 which is used here: https://github.com/grafana/dskit/blob/main/server/server.go#L317 by the server.

Which issue(s) this PR fixes:

This is useful because the certificates can rotate, and with this change we will reload the certificate from the disk without need to restart the application for it.

Fixes #549

Checklist

  • Tests updated
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]

@rubenvp8510 rubenvp8510 force-pushed the allow_rotate_client_certs branch 3 times, most recently from bb05304 to bcfd8c4 Compare July 19, 2024 04:05
Copy link
Contributor

@zalegrala zalegrala left a comment

Choose a reason for hiding this comment

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

This looks reasonable to me. Adhere to the lint check.

Is the expectation here that the server certificate will be reloaded by some other means?

Signed-off-by: Ruben Vargas <[email protected]>
@rubenvp8510
Copy link
Contributor Author

This looks reasonable to me. Adhere to the lint check.

Is the expectation here that the serer certificate will be reloaded by some other means?

The expectation is that at some point the certificate expired, and usually in some platforms there is a logic for cert renewal. But if the certificate is loaded only one time in memory, even if the file changed this won't take effect. Unless you reload it as this PR does. may be an additional improvement will be to not reload each time

@aknuds1 aknuds1 added the enhancement New feature or request label Jul 22, 2024
Copy link
Collaborator

@aknuds1 aknuds1 left a comment

Choose a reason for hiding this comment

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

The idea makes sense to me, but the current implementation doesn't really. I think it changes too much basically, without clear rationale.

CHANGELOG.md Outdated Show resolved Hide resolved
crypto/tls/tls.go Outdated Show resolved Hide resolved
crypto/tls/tls.go Outdated Show resolved Hide resolved
rubenvp8510 and others added 3 commits July 22, 2024 21:13
Co-authored-by: Arve Knudsen <[email protected]>
Co-authored-by: Arve Knudsen <[email protected]>
Co-authored-by: Arve Knudsen <[email protected]>
Copy link
Collaborator

@aknuds1 aknuds1 left a comment

Choose a reason for hiding this comment

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

Looks pretty good now, but validateCertificatePaths is now dead and should be removed. Plus, some other simplifications should be made.

crypto/tls/test/tls_integration_go_1_20_test.go Outdated Show resolved Hide resolved
crypto/tls/test/tls_integration_go_1_21_test.go Outdated Show resolved Hide resolved
crypto/tls/tls_test.go Outdated Show resolved Hide resolved
crypto/tls/tls.go Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
rubenvp8510 and others added 4 commits July 23, 2024 09:27
Co-authored-by: Arve Knudsen <[email protected]>
Co-authored-by: Arve Knudsen <[email protected]>
@rubenvp8510 rubenvp8510 requested review from aknuds1 and zalegrala July 24, 2024 02:05
Copy link
Collaborator

@aknuds1 aknuds1 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for addressing my feedback!

@aknuds1 aknuds1 merged commit 90da908 into grafana:main Jul 24, 2024
5 checks passed
@charleskorn
Copy link
Contributor

This change has broken the TestSingleBinaryWithMemberlist/tls integration test in Mimir (sample logs), it is failing with:

failed to create transport: failed to start TLS TCP listener on "0.0.0.0" port 8000: tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config

Could you please take a look @rubenvp8510? You should be able to pull the branch from grafana/mimir#8833 to reproduce this.

@rubenvp8510
Copy link
Contributor Author

rubenvp8510 commented Jul 29, 2024

Hello @charleskorn I'll take a look today, it seems like the test is expecting one of these to be defined: Certificates, GetCertificate, or GetConfigForClient . Why is not valid to expect a GetClientCertificate ? My understanding if that if you set that you don't need to set Certificates. Also this is for clients., so GetCertificate won't work on this case.

Other thing I can do is set GetConfigForClient, but wondering why this is needed as I only want to make the part of the certificate to be reloaded (which is why I'm using `GetClientCertificate)

@zalegrala
Copy link
Contributor

How goes the testing? I'm seeing the above error in Tempo also after the dskit update.

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

I'm trying to reproduce the test error on my side.

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

Strange, on my side the memberlist-kv module doesn't fail for the reason Charles linked to in CI. For me it fails with a non-informative error:

16:43:20 mimir-1: ts=2024-08-01T14:43:20.847969237Z caller=mimir.go:907 level=error msg="module failed" module=memberlist-kv err="starting module memberlist-kv: invalid service state: Stopping, expected: Running"

@zalegrala
Copy link
Contributor

I'm seeing this in Tempo.

level=error ts=2024-08-01T15:06:58.78706799Z caller=app.go:223 msg="module failed" module=memberlist-kv err="service memberlist_kv failed: failed to create transport: failed to start TLS TCP listener on \"::\" port 7946: tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config"

@rubenvp8510
Copy link
Contributor Author

It seems like in order to not break anything we will need to provide a GetConfigForClient instead, not sure why GetClientCertificate is not enough I'll do the change and send the PR , I expected to have something between today and tomorrow.

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

@charleskorn @rubenvp8510 @zalegrala I think the problem is that memberlist/kv uses a client certificate also for server purposes, that's the reason for the error. As a fix, shall we also set the Certificates field? It shouldn't hurt, since GetClientCertificate overrides it for client purposes. I'm going to test and see if this works.

@rubenvp8510
Copy link
Contributor Author

@aknuds1 that make sense

According to go documentation

Server configurations must set one of Certificates, GetCertificate or
GetConfigForClient. Clients doing client-authentication may set either
Certificates or GetClientCertificate.

This is confusing because the struture is named ClientConfig.

About setting certificates, What I don't know is , if I set certificates then GetClientCertificate will be called? or if this is also used for server, we can set algo GetCertificates method.

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

@rubenvp8510 I agree it's confusing, I don't know yet why memberlist/kv appears to use ClientConfig for a server. Maybe it shouldn't?

About setting certificates, What I don't know is , if I set certificates then GetClientCertificate will be called? or if this is also used for server, we can set algo GetCertificates method.

The GetClientCertificate documentation makes it clear that it masks Certificates for clients. However, it doesn't matter to servers.

// GetClientCertificate, if not nil, is called when a server requests a
// certificate from a client. If set, the contents of Certificates will
// be ignored.

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

I've tested also setting Certificates for backwards compat purposes, that makes the integration test pass. Making a PR.

@rubenvp8510
Copy link
Contributor Author

I've tested also setting Certificates for backwards compat purposes, that makes the integration test pass. Making a PR.

Great! then we can set it with confidence :)

@aknuds1
Copy link
Collaborator

aknuds1 commented Aug 1, 2024

I've made a PR to fix the issue, please review. Tried the broken Mimir integration test with it, it passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Supporting reloading client certificates
4 participants