-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[fix][authentication] Store the original auth when using anonymous role #19390
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
| import org.testng.annotations.Test; | ||
|
|
||
| @Slf4j | ||
| public class ProxyAnonymousRoleTest extends ProducerConsumerBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test group.
| conf.getProperties().setProperty("tokenSecretKey", "data:;base64," + Base64.getEncoder().encodeToString(SECRET_KEY.getEncoded())); | ||
|
|
||
| Set<String> superUserRoles = new HashSet<>(); | ||
| superUserRoles.add(ANONYMOUS_ROLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means the proxy is a superuser. Without this config, the proxy has no permission to communicate.
| private void createAdminClient() throws Exception { | ||
| admin = spy(PulsarAdmin.builder().serviceHttpUrl(brokerUrl.toString()) | ||
| .authentication(AuthenticationFactory.token(ADMIN_TOKEN)).build()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The admin client will not work with proxy for this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any address will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should let the proxy authenticate using an anonymous role. I started work in #19270 to propose that we make stricter requirements so that when a connection is started by a proxy, the authRole must be a proxy role (we know because the command has the originalPrincipal and maybe the originalAuthData). That work is only a draft because of some edge cases that will be resolved by #19409.
I propose that we consider a proxy connecting as the anonymous role as a misconfiguration.
Sound good to me. |
@michaeljmarshall I also agree with this. But I think there is a bug here, when the proxy is an anonymous user, we don't care about storing the original role and original authentication data, so this PR is used to fix this. #19270 is validating the auth role and proxy role to avoid the auth role as the proxy role, the two PR have different goal. |
pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyAnonymousRoleTest.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Zixuan Liu <nodeces@gmail.com>
45eb7e9 to
057703a
Compare
michaeljmarshall
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to discuss taking a different direction. I think we should fail the connection if the proxy connects without a valid authMethod. My proposal is in the comments.
| @@ -971,6 +973,7 @@ protected void handleConnect(CommandConnect connect) { | |||
| authRole = getBrokerService().getAuthenticationService().getAnonymousUserRole() | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just add the following before the call to get the anonymous role? I think this would correctly handle the issue of a proxy authenticating as the anonymous role.
if (connect.hasOriginalPrincipal() || connect.hasOriginalAuthData()) {
throw new AuthenticationException("Proxy cannot authenticate as the anonymous role.");
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that the proxy cannot use the anonymous role to connect to the broker, I don't think this is correct.
Usually, the proxy always enable the authentication feature, but we also should consider a case that the proxy doesn't enable the authentication feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that the proxy cannot use the anonymous role to connect to the broker
Yes, this is the design I am proposing we move towards. That is why I said this earlier in this PR:
I propose that we consider a proxy connecting as the anonymous role as a misconfiguration.
Usually, the proxy always enable the authentication feature, but we also should consider a case that the proxy doesn't enable the authentication feature.
In this case, the broker wouldn't enable authentication either. In the admin API, we only look for the original principal when the authRole is in the proxyRoles set. Given that the proxy has to have at least as much permission as the originalPrincipal, I do not see what the point of authentication would be if the anonymous role is also a proxy role.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your idea is very true, we also recommend enabling authentication anywhere.
We have a case in which we don't want to check the proxy authentication in the broker, only check the original authentication. Would you have any idea?
Right now, we set up anonymousUserRole, but we cannot get the original authentication, because of the broker jumped to completeConnect method, there is misses storing the original authentication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a case in which we don't want to check the proxy authentication in the broker, only check the original authentication. Would you have any idea?
That context helps a lot, thanks! Is it possible to add a configuration to the proxy so that it forwards the original authentication data as the authData part of the Connect command? The broker wouldn't necessarily know the connection is from the proxy, but I think this should be fine.
I think this discussion probably relates to #19332. I have been thinking that our authentication state integration between proxy and broker is very complicated and doesn't appear to be working in all cases (see also #19291).
It seems like we could always drop the proxy auth data in cases where the authentication data can be forwarded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, we need to improve the proxy codebase to find a workaround, this is going to take some time.
| authRole = getBrokerService().getAuthenticationService().getAnonymousUserRole() | ||
| .orElseThrow(() -> | ||
| new AuthenticationException("No anonymous role, and no authentication provider configured")); | ||
| checkAndStoreOriginalAuthDataForwardedByProxy(connect); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern with this solution is that it lets a proxy connect as the anonymous role, and I don't think that will work correctly. Note that we do not use the anonymousRole for the originalPrincipal, so it seems to me that the anonymousRole is only meant for direct broker access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right.
| } | ||
|
|
||
| @Test | ||
| public void testAuthorizationWithProxyAsAnonymousRoleWithOriginalRole() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do go with my proposed restriction, it might be helpful to use the ServerCnxTest class to validate how the Connect command behaves. If you look through the commit history on that file, you'll see that I've added several authentication related tests that allow for low level manipulation of the protocol without much need for mocking.
|
The pr had no activity for 30 days, mark with Stale label. |
Motivation
When
anonymousUserRoleis configured, and auth method isnone, the broker only stores theauthRole, ignores store the original authentication data and role forwarded by the proxy, seepulsar/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/ServerCnx.java
Lines 898 to 904 in b3432f4
We have to store the forwarded authentication data and role, the data from
CommandConnect#getOriginalAuthData, and the role fromCommandConnect#getOriginalPrincipal.Modifications
checkAndStoreOriginalAuthDataForwardedByProxymethod to check and store the original authenticationVerifying this change
Added
ProxyAnonymousRoleTesttest.Documentation
docdoc-requireddoc-not-neededdoc-complete