-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-6750: Add listener name to authentication context (KIP-282) #4829
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
Changes from 3 commits
9c519d7
70bd84e
bada354
d069e0a
4dd4203
132d4df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,15 @@ | |
| public class PlaintextChannelBuilder implements ChannelBuilder { | ||
| private static final Logger log = LoggerFactory.getLogger(PlaintextChannelBuilder.class); | ||
| private Map<String, ?> configs; | ||
| private final ListenerName listenerName; | ||
|
|
||
| /** | ||
| * Constructs a plaintext channel builder. ListenerName is provided only | ||
| * for server channel builder and will be null for client channel builder. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's actually a bit more complicated. It's non-null whenever it's instantiated in the broker and null otherwise. In the broker case, we create both server and client channel builders, but it's set in both (for sending and receiving requests respectively). |
||
| */ | ||
| public PlaintextChannelBuilder(ListenerName listenerName) { | ||
| this.listenerName = listenerName; | ||
| } | ||
|
|
||
| public void configure(Map<String, ?> configs) throws KafkaException { | ||
| this.configs = configs; | ||
|
|
@@ -43,7 +52,7 @@ public void configure(Map<String, ?> configs) throws KafkaException { | |
| public KafkaChannel buildChannel(String id, SelectionKey key, int maxReceiveSize, MemoryPool memoryPool) throws KafkaException { | ||
| try { | ||
| PlaintextTransportLayer transportLayer = new PlaintextTransportLayer(key); | ||
| PlaintextAuthenticator authenticator = new PlaintextAuthenticator(configs, transportLayer); | ||
| PlaintextAuthenticator authenticator = new PlaintextAuthenticator(configs, transportLayer, listenerName); | ||
| return new KafkaChannel(id, transportLayer, authenticator, maxReceiveSize, | ||
| memoryPool != null ? memoryPool : MemoryPool.NONE); | ||
| } catch (Exception e) { | ||
|
|
@@ -58,10 +67,12 @@ public void close() {} | |
| private static class PlaintextAuthenticator implements Authenticator { | ||
| private final PlaintextTransportLayer transportLayer; | ||
| private final KafkaPrincipalBuilder principalBuilder; | ||
| private final ListenerName listenerName; | ||
|
|
||
| private PlaintextAuthenticator(Map<String, ?> configs, PlaintextTransportLayer transportLayer) { | ||
| private PlaintextAuthenticator(Map<String, ?> configs, PlaintextTransportLayer transportLayer, ListenerName listenerName) { | ||
| this.transportLayer = transportLayer; | ||
| this.principalBuilder = ChannelBuilders.createPrincipalBuilder(configs, transportLayer, this, null); | ||
| this.listenerName = listenerName; | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -70,7 +81,9 @@ public void authenticate() throws IOException {} | |
| @Override | ||
| public KafkaPrincipal principal() { | ||
| InetAddress clientAddress = transportLayer.socketChannel().socket().getInetAddress(); | ||
| return principalBuilder.build(new PlaintextAuthenticationContext(clientAddress)); | ||
| // listenerName should only be null in Client mode | ||
| String listenerNameStr = listenerName != null ? listenerName.value() : null; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems a bit brittle. Maybe the field should be
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should never be calling
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably not have the null check then, better fail fast. Same for the other case. |
||
| return principalBuilder.build(new PlaintextAuthenticationContext(clientAddress, listenerNameStr)); | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,9 +18,11 @@ | |
|
|
||
| import java.net.InetAddress; | ||
|
|
||
|
|
||
| /** | ||
| * An object representing contextual information from the authentication session. See | ||
| * {@link SaslAuthenticationContext} and {@link SslAuthenticationContext}. | ||
| * {@link PlaintextAuthenticationContext}, {@link SaslAuthenticationContext} | ||
| * and {@link SslAuthenticationContext}. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should mention that this class is only used in the broker. |
||
| */ | ||
| public interface AuthenticationContext { | ||
| /** | ||
|
|
@@ -32,4 +34,9 @@ public interface AuthenticationContext { | |
| * Address of the authenticated client | ||
| */ | ||
| InetAddress clientAddress(); | ||
|
|
||
| /** | ||
| * Name of the listener used for the connection | ||
| */ | ||
| String listenerName(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,15 +17,18 @@ | |
| package org.apache.kafka.common.security.auth; | ||
|
|
||
| import javax.net.ssl.SSLSession; | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this intentional? |
||
| import java.net.InetAddress; | ||
|
|
||
| public class SslAuthenticationContext implements AuthenticationContext { | ||
| private final SSLSession session; | ||
| private final InetAddress clientAddress; | ||
| private final String listenerName; | ||
|
|
||
| public SslAuthenticationContext(SSLSession session, InetAddress clientAddress) { | ||
| public SslAuthenticationContext(SSLSession session, InetAddress clientAddress, String listenerName) { | ||
| this.session = session; | ||
| this.clientAddress = clientAddress; | ||
| this.listenerName = listenerName; | ||
| } | ||
|
|
||
| public SSLSession session() { | ||
|
|
@@ -41,4 +44,9 @@ public SecurityProtocol securityProtocol() { | |
| public InetAddress clientAddress() { | ||
| return clientAddress; | ||
| } | ||
|
|
||
| @Override | ||
| public String listenerName() { | ||
| return listenerName; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |
| import org.apache.kafka.common.security.auth.KafkaPrincipalBuilder; | ||
| import org.apache.kafka.common.security.auth.PlaintextAuthenticationContext; | ||
| import org.apache.kafka.common.security.auth.PrincipalBuilder; | ||
| import org.apache.kafka.common.security.auth.SecurityProtocol; | ||
| import org.easymock.EasyMock; | ||
| import org.junit.Test; | ||
|
|
||
|
|
@@ -38,7 +39,6 @@ | |
| public class ChannelBuildersTest { | ||
|
|
||
| @Test | ||
| @SuppressWarnings("deprecation") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we remove this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test does not use any deprecated classes, so it's unecessary
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, |
||
| public void testCreateOldPrincipalBuilder() throws Exception { | ||
| TransportLayer transportLayer = EasyMock.mock(TransportLayer.class); | ||
| Authenticator authenticator = EasyMock.mock(Authenticator.class); | ||
|
|
@@ -51,7 +51,7 @@ public void testCreateOldPrincipalBuilder() throws Exception { | |
| assertTrue(OldPrincipalBuilder.configured); | ||
|
|
||
| // test delegation | ||
| KafkaPrincipal principal = builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost())); | ||
| KafkaPrincipal principal = builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost(), SecurityProtocol.PLAINTEXT.name())); | ||
| assertEquals(OldPrincipalBuilder.PRINCIPAL_NAME, principal.getName()); | ||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,19 +53,19 @@ public void testUseOldPrincipalBuilderForPlaintextIfProvided() throws Exception | |
| DefaultKafkaPrincipalBuilder builder = DefaultKafkaPrincipalBuilder.fromOldPrincipalBuilder(authenticator, | ||
| transportLayer, oldPrincipalBuilder, null); | ||
|
|
||
| KafkaPrincipal principal = builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost())); | ||
| KafkaPrincipal principal = builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost(), SecurityProtocol.PLAINTEXT.name())); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few long lines in this class. The goal is that they should fit within the GitHub window. |
||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| assertEquals("foo", principal.getName()); | ||
|
|
||
| builder.close(); | ||
|
|
||
| verifyAll(); | ||
| } | ||
|
|
||
| @Test | ||
| public void testReturnAnonymousPrincipalForPlaintext() throws Exception { | ||
| DefaultKafkaPrincipalBuilder builder = new DefaultKafkaPrincipalBuilder(null); | ||
| assertEquals(KafkaPrincipal.ANONYMOUS, builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost()))); | ||
| assertEquals(KafkaPrincipal.ANONYMOUS, builder.build(new PlaintextAuthenticationContext(InetAddress.getLocalHost(), SecurityProtocol.PLAINTEXT.name()))); | ||
| builder.close(); | ||
| } | ||
|
|
||
| @Test | ||
|
|
@@ -86,12 +86,11 @@ public void testUseOldPrincipalBuilderForSslIfProvided() throws Exception { | |
| DefaultKafkaPrincipalBuilder builder = DefaultKafkaPrincipalBuilder.fromOldPrincipalBuilder(authenticator, | ||
| transportLayer, oldPrincipalBuilder, null); | ||
|
|
||
| KafkaPrincipal principal = builder.build(new SslAuthenticationContext(session, InetAddress.getLocalHost())); | ||
| KafkaPrincipal principal = builder.build(new SslAuthenticationContext(session, InetAddress.getLocalHost(), SecurityProtocol.PLAINTEXT.name())); | ||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| assertEquals("foo", principal.getName()); | ||
|
|
||
| builder.close(); | ||
|
|
||
| verifyAll(); | ||
| } | ||
|
|
||
|
|
@@ -105,10 +104,11 @@ public void testUseSessionPeerPrincipalForSsl() throws Exception { | |
|
|
||
| DefaultKafkaPrincipalBuilder builder = new DefaultKafkaPrincipalBuilder(null); | ||
|
|
||
| KafkaPrincipal principal = builder.build(new SslAuthenticationContext(session, InetAddress.getLocalHost())); | ||
| KafkaPrincipal principal = builder.build(new SslAuthenticationContext(session, InetAddress.getLocalHost(), SecurityProtocol.PLAINTEXT.name())); | ||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| assertEquals("foo", principal.getName()); | ||
|
|
||
| builder.close(); | ||
| verifyAll(); | ||
| } | ||
|
|
||
|
|
@@ -124,10 +124,11 @@ public void testPrincipalBuilderScram() throws Exception { | |
| DefaultKafkaPrincipalBuilder builder = new DefaultKafkaPrincipalBuilder(null); | ||
|
|
||
| KafkaPrincipal principal = builder.build(new SaslAuthenticationContext(server, | ||
| SecurityProtocol.SASL_PLAINTEXT, InetAddress.getLocalHost())); | ||
| SecurityProtocol.SASL_PLAINTEXT, InetAddress.getLocalHost(), SecurityProtocol.SASL_PLAINTEXT.name())); | ||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| assertEquals("foo", principal.getName()); | ||
|
|
||
| builder.close(); | ||
| verifyAll(); | ||
| } | ||
|
|
||
|
|
@@ -146,10 +147,11 @@ public void testPrincipalBuilderGssapi() throws Exception { | |
| DefaultKafkaPrincipalBuilder builder = new DefaultKafkaPrincipalBuilder(kerberosShortNamer); | ||
|
|
||
| KafkaPrincipal principal = builder.build(new SaslAuthenticationContext(server, | ||
| SecurityProtocol.SASL_PLAINTEXT, InetAddress.getLocalHost())); | ||
| SecurityProtocol.SASL_PLAINTEXT, InetAddress.getLocalHost(), SecurityProtocol.SASL_PLAINTEXT.name())); | ||
| assertEquals(KafkaPrincipal.USER_TYPE, principal.getPrincipalType()); | ||
| assertEquals("foo", principal.getName()); | ||
|
|
||
| builder.close(); | ||
| verifyAll(); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -331,7 +331,7 @@ abstract class EndToEndAuthorizationTest extends IntegrationTestHarness with Sas | |
| } | ||
| } | ||
|
|
||
| private def sendRecords(numRecords: Int, tp: TopicPartition) { | ||
| protected def sendRecords(numRecords: Int, tp: TopicPartition) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| val futures = (0 until numRecords).map { i => | ||
| val record = new ProducerRecord(tp.topic(), tp.partition(), s"$i".getBytes, s"$i".getBytes) | ||
| debug(s"Sending this record: $record") | ||
|
|
||
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.
static fields first, then final, then mutable.