Date: Tue, 19 Mar 2024 05:04:14 +0000 (UTC) Message-ID: <558107490.54335.1710824654338@cwiki-he-fi.apache.org> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_54334_497994644.1710824654338" ------=_Part_54334_497994644.1710824654338 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
Current state: Closed (Covered by KIP-189)
=
Discussion thread: (Original Archive) (Markmail)
JIRA: KAFKA-4454=
Released: <Kafka Version>
Please keep the discussion on the mailing list rather than commenting on= the wiki (wiki discussions get unwieldy fast).
Kafka allows users to plugin a custom PrincipalBuilder
and =
a custom Authorizer
by specifying the classpath of the corresp=
onding classes in the config.
When a Kafka broker receives request bytes from clients over the socket =
channel, it reconstructs the request which is then handed over to the reque=
st handler threads (a.k.a API threads) to process the request. In the =
process of doing this, the Kafka broker constructs a Session
o=
bject that holds a KafkaPrincipal
and client's socket IP addre=
ss. The KafkaPrincipal
inclu=
des the type of the client principal ("User"&=
nbsp;as of now) and the name of the Principal
, generated by th=
e PrincipalBuilder
. The Authorizer
interface=
includes an authorize(...) method, that is invoked on every reque=
st that is received by the Kafka broker. If the broker has a custom A=
uthorizer
configured, it will delegate the authorize(...) c=
all to the custom implementation. The authorize(...) method takes =
in the Session
object, Operation
requested =
and the Resource
on which the operation is requested, as metho=
d parameters and returns true or false depending on the configured ACLs as =
follows :
def authoriz= e(session: Session, operation: Operation, resource: Resource): Boolean
However, the principals generated by the plugged in PrincipalBuild=
er
may contain additional custom fields, and the user's Author=
izer
implementation may need to access those fields in order to enfo=
rce ACLs correctly for those principals. Unfortunately, Kafka currentl=
y only extracts the name of the Principal
when constructing th=
e Session
object as shown below, and loses the additional info=
rmation at runtime:
val session = =3D RequestChannel.Session(new KafkaPrincipal(KafkaPrincipal.USER_TYPE, cha= nnel.principal.getName), channel.socketAddress) // (custom fields in princi= pal if any are not passed through)
It is important to note that Java's Principal
API=
is opaque and different Kafka service providers can have custom implementa=
tions of the Principal
interface with additional fea=
tures as per their requirements. Since Kafka allows users to plug in =
a custom PrincipalBuilder
and a custom Au=
thorizer
, it does not make sense to extract only the name of the&nbs=
p;Principal
and ignore the other fields in the generated&=
nbsp;Principal
(which may be required by the custom =
Authorizer).
This issue can be addressed if Kafka preserves the original Princi=
pal
object when it processes the incoming request, before handing it=
over to the API threads. The Authorizer
will then be able to =
access this Principal
object and use it to verify the ACLs.
This KIP introduces a change to Session
class to accept a p=
arameter of Java Principal
type instead of KafkaPr=
incipal
type.
This change will not affect the default ACL Authorizer
(KafkaPrincipal<=
/code> from the
Java Principal
in the default Authorizer=
.
Change the Session
class to accept a parameter of type =
Java Principal
instead of KafkaPrincipal
.
case class = Session(principal: Principal, clientAddress: InetAddress)
The Authorizer
can access this principal object as foll=
ows :
public bool= ean authorize(RequestChannel.Session session, Operation operation, Resource= resource) { ... Principal principal =3D session.principal(); User_Defined_Principal principal =3D (User_Defined_Principal) principal; = =20 ... }
User_Defined_Principal
is the Principal
ge=
nerated by the PrincipalBuilder
and it implements Java P=
rincipal.
What impact (if any) will there be on existing users?
There is no compatibility impact as there is no change in behavior.<= br>
- Unit tests to validate that new changes work as expected without =
affecting the existing behavior.
Alternative 1 :
Kafka-acls.sh will allow to specify a custom PrincipalBuilder<=
/code> using a new command line parameter "-- principalBuilder" and
P=
rincipalBuilder
configs using a new command line parameter "--princi=
palBuilder-properties". Users can use these to build their custom Pri=
ncipal
(that implements Java Principal
). Add a new API =
to PrincipalBuilder
Interface :
public inte= rface PrincipalBuilder extends Configurable { ... /** * Build a Principal using name. * * @param name Principal name * @return Principal */ Principal buildPrincipal(String name); =20 ... }
PrincipalBuilder
API will then be used to generate a =
Principal
using the names specified in --allow-principal and -=
-deny-principal parameters. This Principal
can be included in =
KafkaPrincipal
using the new constructor specified above.Since the Principal
is built using the "--principalBuil=
der-properties", users can only specify a particular type of Principa=
l
(s) (using --allow-principal / --deny-principal) at a time.
If users want to specify multiple types of Principals, they will hav=
e to run the kafka-acls.sh multiple times with different "--principalBuilde=
r-properties", even if the Principals might have the same name. For example=
, we can have a service Principal
with name "XYZ" and a user <=
code>Principal with name "XYZ".
Alternative 2 :
Changes to kafka-acls.sh
PrincipalBuilder class using a new command line parameter "-- principalBuilder"=
and PrincipalBuilder
configs using a new command line paramet=
er "--principalBuilder-properties".
The "--allow-principal" will take list of properties as fol= lows :
bin/kafka-a= cls.sh ...... --principalBuilder <PrincipalBuilder-class> --principal= Builder-properties <PrincipalBuilder-properties> --add --allow-princi= pal <principal-properties> --allow-principal <principal-properties= > ...... --operations Read,Write --topic Test-topic
Add a new API to PrincipalBuilder
:
public inte= rface PrincipalBuilder extends Configurable { ... /** * Build a Principal using the provided configs. * * @param principalConfigs configs used to create the Principal * @return Principal */ Principal buildPrincipal(Map<String, ?> principalConfigs); ... }
PrincipalBuilder
class will be responsible f=
or building the Principal
using the <principal-properties&g=
t;.Principal
generated by this PrincipalBuilder can then be included in KafkaPrincipal
using the new const=
ructor specified above.
The "--principalBuilder" and "--principalBuilder-properties= " parameters are optional. If its not specified, the Kafka-acls.sh wou= ld still work as it does today.