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

feat: peer cert as username #775

Merged
merged 5 commits into from
Sep 29, 2023
Merged

feat: peer cert as username #775

merged 5 commits into from
Sep 29, 2023

Conversation

MikeDombo
Copy link
Contributor

@MikeDombo MikeDombo commented Sep 18, 2023

Rebase of #675

This PR adds enables authenticating clients based on their peer certificates without changing the existing authentication interface. This functionality is enabled by the addition of a new configuration option which passes the client certificate PEM in place of username. The EMQx broker also has the same configuration option.

There is also a very small change to behavior with this PR. Previously, clients that did not provide a password were immediately rejected if anonymous sessions were disabled. As far as I can tell, the spec allows username without a password. The code will now allow this and pass the username and empty password to the authenticator.

Why is this needed?
The existing auth interfaces are insufficient when clients need to be identified based on their client certificate. The current interfaces only support username, password, and client ID without any ability for authenticators and authorizers to use the client certificate (if provided) for authN/authZ.

By passing in the client certificate as username, this allows the authorizer to uniquely identify clients and authenticate and authorize based on this cryptographically secure identity.

Close #675

@MikeDombo
Copy link
Contributor Author

@andsel rebased PR ready for your review. The peer cert behavior is behind a BrokerConfiguration flag which is disabled by default.

@andsel andsel self-requested a review September 28, 2023 14:05
Copy link
Collaborator

@andsel andsel 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 seems good, however I would add an integration test with a real client that uses TLS connection and the server that validates the client identity using the provided certificate.

for (Certificate certificate : certificates) {
pemWriter.writeObject(certificateBoundaryType, certificate.getEncoded());
}
pemWriter.close();
Copy link
Collaborator

Choose a reason for hiding this comment

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

But pemWriter isn't closed automatically by the try statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is closed automatically yes, however it needs to be closed before calling str.toString() or else the str will not contain the correct contents due to the buffered nature of BufferedWriter which PemWriter extends.

@andsel
Copy link
Collaborator

andsel commented Sep 28, 2023

If the authorizer allows the operation, then a malicious client could exploit this to publish (or subscribe) to topics it should not normally be authorized on.

If the authorizer assumes that the operation is coming from the old client and denies the operation, then it is possible for operations which should be allowed to be be silently rejected (as Moquette does not disconnect clients after authZ failures).

Please could you describe better?
Then, do you think that if authz fails, Moquette should close the connection? I think this is a weakness in Moquette, so could be a separate issue (in case file one issue for that)

@MikeDombo
Copy link
Contributor Author

MikeDombo commented Sep 28, 2023

Thank you for the review @andsel.

I've updated the simple parts for formatting and extracting method.

I would add an integration test with a real client that uses TLS connection and the server that validates the client identity using the provided certificate.

Are there any existing integration tests that you can point to which use either TLS or better yet, mutual TLS with client certs? Nevermind, I found ServerIntegrationSSLClientAuthTest.

As for the authorizer bit of the description, I took that from the previous PR and it is possible that it no longer applies due to the significant session changes from 0.15 to 0.17. The idea was that an implementor of IAuthorizatorPolicy only gets the client ID and no other identifying information, so if the authorizer is caching information based on the client ID, then a malicious client connecting with the same client ID would inherit the permissions from the trusted client.

I will update the description to simplify since this is really just about providing a nicer way to offer TLS mutual auth for devices with client certificates.

As a separate point to this PR, yes I do think that unauthorized actions should kick the client (at least as an option); this is what AWS IoT Core does.

@MikeDombo
Copy link
Contributor Author

Added more testing with real TLS.

@andsel andsel self-requested a review September 29, 2023 08:43
Copy link
Collaborator

@andsel andsel left a comment

Choose a reason for hiding this comment

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

Thanks a lot @MikeDombo for this. I've a concern about setup method, if you could separate would be great.
Add also a line in the Changelog please 🙏

Thanks for the effort in sustaining the project.

Copy link
Collaborator

@andsel andsel left a comment

Choose a reason for hiding this comment

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

We are really close, just one refactoring step and then the PR is perfect to be merged, I think.

Copy link
Collaborator

@andsel andsel left a comment

Choose a reason for hiding this comment

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

LGTM

@andsel andsel merged commit 154d365 into moquette-io:main Sep 29, 2023
4 checks passed
@andsel andsel added the v0.18.0 label Sep 29, 2023
@MikeDombo MikeDombo deleted the peercert branch September 29, 2023 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants